• Stars
    star
    651
  • Rank 69,175 (Top 2 %)
  • Language
    Swift
  • License
    Apache License 2.0
  • Created over 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A framework for advanced NSOperations usage

PSOperations

codebeat badge Build Status

PSOperations is a framework that leverages the power of NSOperation and NSOperationQueue. It enables you to use operations more easily in all parts of your project.

This is an adaptation of the sample code provided in the Advanced NSOperations session of WWDC 2015.

Support

  • Swift 5.x
  • iOS 8.0
  • tvOS 9.0
  • watchOS (undefined deployment target)
  • macOS 10.11
  • Extension friendly
  • Tests only run against iOS 9 (latest) and tvOS 9 (latest)

Swift 3+

Because Swift 3 removes the NS prefix on several Foundation types we've added a few typealiases for convenience. We investigated renaming the few classes that conflict but ran into radar://28917706 where frameworks will fallback to Foundation types if the framework doesn't contain the given type i.e. UIKit.Data is valid and really is Foundation.Data. If we were to rename Operation to PSOperation usuages of PSOperations.Operation would end up using Foundation.Operation and potentially break your code.

Here are the typealiases:

public typealias PSOperation = Operation
public typealias PSOperationQueue = OperationQueue
public typealias PSOperationQueueDelegate = OperationQueueDelegate
public typealias PSBlockOperation = BlockOperation

Installation

PSOperations supports multiple methods for installing the library in a project.

Swift Package Manager

The Swift Package Manager (SPM) is Swift's own dependency management as of Swift 3.0. Xcode 11 gained native support for SPM and allows to add dependencies to apps from within Xcode.

PSOperations can be added either via Xcode 11+, or by adding the following dependency to your Package.swift:

.package(url: "https://github.com/pluralsight/PSOperations.git", from: "5.0.2"),

CocoaPods

CocoaPods is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like PSOperations in your projects.

You can install it with the following command:

$ gem install cocoapods

To integrate PSOperations into your Xcode project using CocoaPods, specify it in your Podfile.
If you want all the child subspecs (Health and Passbook capabilities):

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

target 'TargetName' do
pod 'PSOperations', '~> 4.0'
end

Then, run the following command:

$ pod install

Alternative configurations:
Core functionality, excluding capabilities:

pod 'PSOperations/Core', '~> 4.0'

Core functionality, including only the Passbook capability:

pod 'PSOperations/Passbook', '~> 4.0'

Core functionality, including only the Health capability:

pod 'PSOperations/Health', '~> 4.0'

Core functionality, including only the Calendar capability:

pod 'PSOperations/Calendar', '~> 4.0'

Core functionality, including only the Location capability and operation:

pod 'PSOperations/Location', '~> 4.0'

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate PSOperations into your Xcode project using Carthage, specify it in your Cartfile:

github "pluralsight/PSOperations"

Run carthage to build the framework and drag the built PSOperations.framework into your Xcode project. Optionally you can add PSOperationsHealth.framework, PSOperationsPassbook.framework, PSOperationsCalendar.framework and PSOperationsLocation.framework

Getting started

Don't forget to import!

import PSOperations

If you are using the HealthCapability, PassbookCapability, CalendarCapability, LocationCapability or LocationOperation you'll need to import them separately:

import PSOperationsHealth
import PSOperationsPassbook
import PSOperationsCalendar
import PSOperationsLocation

These features need to be in a separate framework otherwise they may cause App Store review rejection for importing HealthKit, PassKit, EventKit or CoreLocation but not actually using them.

Create a Queue

The OperationQueue is the heartbeat and is a subclass of NSOperationQueue:

let operationQueue = OperationQueue()

Create an Operation

Operation is a subclass of NSOperation. Like NSOperation it doesn't do much. But PSOperations provides a few helpful subclasses such as:

BlockOperation
GroupOperation
URLSessionTaskOperation
LocationOperation
DelayOperation

Here is a quick example:

let blockOperation = BlockOperation {
	print("perform operation")
}

operationQueue.addOperation(blockOperation)

Observe an Operation

Operation instances can be observed for starting, cancelling, finishing and producing new operations with the OperationObserver protocol.

PSOperations provide a couple of types that implement the protocol:

BlockObserver
TimeoutObserver

Here is a quick example:

let blockOperation = BlockOperation {
	print("perform operation")
}

let finishObserver = BlockObserver { operation, error in        
	print("operation finished! \(error)")
}

blockOperation.addObserver(finishObserver)

operationQueue.addOperation(blockOperation)

Set Conditions on an Operation

Operation instances can have conditions required to be met in order to execute using the OperationCondition protocol.

PSOperations provide a several types that implement the protocol:

SilentCondition
NegatedCondition
NoCancelledDependencies
MutuallyExclusive
ReachabilityCondition
Capability

Here is a quick example:

let blockOperation = BlockOperation {
	print("perform operation")
}

let dependentOperation = BlockOperation {
	print("working away")
}
                dependentOperation.addCondition(NoCancelledDependencies())
dependentOperation.addDependency(blockOperation)

operationQueue.addOperation(blockOperation)
operationQueue.addOperation(dependentOperation)

if blockOperation is cancelled, dependentOperation will not execute.

Set Capabilities on an Operation

A CapabilityType is used by the Capability condition and allows you to easily view the authorization state and request the authorization of certain capabilities within Apple's ecosystem. i.e. Calendar, Photos, iCloud, Location, and Push Notification.

Here is a quick example:

let blockOperation = BlockOperation {
	print("perform operation")
}


let calendarCapability = Capability(Photos())
        
blockOperation.addCondition(calendarCapability)

operationQueue.addOperation(blockOperation)

This operation requires access to Photos and will request access to them if needed.

Going custom

The examples above provide simple jobs but PSOperations can be involved in many parts of your application. Here is a custom UIStoryboardSegue that leverages the power of PSOperations. The segue is retained until an operation is completed. This is a generic OperationSegue that will run any given operation. One use case for this might be an authentication operation that ensures a user is authenticated before preceding with the segue. The authentication operation could even present authentication UI if needed.

class OperationSegue: UIStoryboardSegue {
    
    var operation: Operation?
    var segueCompletion: ((success: Bool) -> Void)?
    
    override func perform() {        
        if let operation = operation {
            let opQ = OperationQueue()
            var retainedSelf: OperationSegue? = self
            
            let completionObserver = BlockObserver {
                op, errors in
                
                dispatch_async_on_main {
                    defer {
                        retainedSelf = nil
                    }
                    
                    let success = errors.count == 0 && !op.cancelled
                    
                    if let completion = retainedSelf?.segueCompletion {
                        completion(success: success)
                    }
                    
                    if success {
                        retainedSelf?.finish()
                    }
                }
            }
            
            operation.addObserver(completionObserver)
            opQ.addOperation(operation)
        } else {
            finish()
        }
    }
    
    func finish() {
        super.perform()
    }
}

Contribute

Feel free to submit pull requests, as we are always looking for improvements from the community.

WWDC Differences

Differences from the first version of the WWDC sample code:

  • Canceling operations would not work.
  • Canceling functions are slightly more friendly.
  • Negated Condition would not negate.
  • Unit tests!

Differences from the second version of the WWDC sample code:

  • Sometimes canceling wouldn't work correctly in iOS 8.4. The finished override wasn't being called during cancel. We have fixed this to work in both iOS 8.4 and iOS 9.0.
  • Canceling functions are slightly more friendly.
  • Unit tests!

A difference from the WWDC Sample code worth mentioning:

  • When conditions are evaluated and they fail the associated operation is cancelled. The operation still goes through the same flow otherwise, only now it will be marked as cancelled.

More Repositories

1

git-internals-pdf

PDF on Git Internals
Ruby
2,452
star
2

guides

Article back-end for hack.guides() website
635
star
3

intro-to-pytest

An introduction to PyTest with lots of simple, hackable examples
Python
332
star
4

classic-design-system

This library (classic) is officially in maintenance mode only. For the latest library, please see the TVA project (https://pluralsight.github.io/tva/).
TypeScript
296
star
5

web-dev-starter

HTML
272
star
6

PS-AutoLab-Env

A PowerShell module for creating lab configurations using Lability and Desired State Configuration. This is a complete update of the 3.x versions. Look at README.md for more information.
PowerShell
261
star
7

react-styleable

React Component for portable styles
JavaScript
220
star
8

guides-cms

DEPRECATED - Markdown based CMS with Github repository as persistent storage
Python
109
star
9

hydra

A real-time data replication platform that "unbundles" the receiving, transforming, and transport of data streams.
Scala
82
star
10

mob-timer

A mob programming application
JavaScript
62
star
11

hydra-spark

Scala
49
star
12

irt_parameter_estimation

Parameter estimation routines for logistic Item Characteristic Curves (ICC) from Item Response Theory (IRT)
Python
47
star
13

pando

🌲 The foundational roots to a better design system using Pluralsight Design.
TypeScript
46
star
14

maybe-dotnet

C#
41
star
15

pluralsight-author-contrib

Pluralsight author related materials
37
star
16

tech-blog-fastapi-demo

sample code for tech blog post "Porting Flask to FastAPI for ML Model Serving"
Python
30
star
17

htmlTagValidator

HTML Tag validator that does not rely on the DOM
JavaScript
28
star
18

spavro

Spavro is a (sp)eedier avro library -- Spavro is a fork of the official Apache AVRO python 2 implementation with the goal of greatly improving data read deserialization and write serialization performance.
Python
25
star
19

redux-react-connector

Convenient subscription to redux stores
JavaScript
24
star
20

applenotary

A CLI for synchronously notarizing macOS applications
Swift
22
star
21

tech-blog-roll-the-dice

example code for blog post "Python CLI Utilities with Poetry and Typer"
Python
11
star
22

git-collaborate

Cross-platform electron app for managing git users while pair/mob programming
JavaScript
8
star
23

intro-to-python-typing

An introduction to Python 3 type annotations, using lots of simple, hackable examples
8
star
24

Clean-Code-The-Polyglot-Edition

A collaborative attempt to translate the language-specific code examples and recommendations from Robert C. Martin's "Clean Code" into other languages.
Python
8
star
25

FocusableView

Swift
7
star
26

team-exercises

A repo containing some team training material
JavaScript
5
star
27

git-switch

This is a Windows utility that allows multiple users to share a pairing station while using their own creds for commits.
C#
5
star
28

BlackCat

Centralized reporting on GitHub dependency scanning outputs
Python
4
star
29

spark-analytics

3
star
30

ps-python-library-public

Collection of reusable python modules that are used for data processing
Python
3
star
31

pando-rfcs

RFCs for changes to any Pando related library
3
star
32

sparse_dot

Highly efficient dot products using sparse arrays (in location/data form)
Python
3
star
33

gsweet

Help with writing scripts to run against gSuite
JavaScript
2
star
34

activity-insights-vim

Vim extension for the ps-time product
Vim Script
2
star
35

hydra-notifications

A generic RESTful API to send notifications to different systems through an HTTP endpoint.
Scala
2
star
36

hydra-avro-utils

A collection of Avro utilities to facilitate the handling of streams containg Avro messages.
Scala
2
star
37

HHPS-Partner-Tutorials

Private articles repo
2
star
38

a11y-test-app

Client-side app reserved for a11y testing and validation for PSDS usage.
TypeScript
1
star
39

psqlx

A wrapper around psql that makes interacting with psql and your .pgpass files easier
PowerShell
1
star
40

Bless.Net

CSS
1
star
41

mtm_stats

Highly efficient set statistics about many-to-many relationships
Python
1
star
42

ps-wait

Wait for a condition to be met
JavaScript
1
star
43

trello-helper

Help make calls to the Trello API simple.
TypeScript
1
star
44

gcf-ts-starter-kit

A Google Cloud Function Typescript Starter Kit
JavaScript
1
star
45

env-verifier

Save yourself a headache by verifying your incoming .env variables
TypeScript
1
star
46

lessons-learned

Lessons learned using typescript and Node
TypeScript
1
star
47

pairing-station

A charming little OS X app to manage identities on a pairing station.
Objective-C
1
star
48

activity-insights-cli

The command line interface used in the Pluralsight Activity Insights dashboard. The dashboard is currently in public beta for Pluralsight users while we gather feedback.
Rust
1
star