├── Pod
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── iOS
│ ├── Conditions
│ │ ├── OPPhotosCondition.h
│ │ ├── OPAudioCondition.h
│ │ ├── OPVideoCondition.h
│ │ ├── OPLocationCondition.h
│ │ ├── OPOperationConditionUserNotification.h
│ │ ├── OPRemoteNotificationCondition.h
│ │ ├── OPAudioCondition.m
│ │ ├── OPVideoCondition.m
│ │ ├── OPPhotosCondition.m
│ │ └── OPOperationConditionUserNotification.m
│ ├── Observers
│ │ ├── OPNetworkObserver.h
│ │ ├── OPBackgroundObserver.h
│ │ ├── OPBackgroundObserver.m
│ │ └── OPNetworkObserver.m
│ ├── Categories
│ │ ├── UIUserNotificationSettings+Operative.h
│ │ └── UIUserNotificationSettings+Operative.m
│ └── Operations
│ │ ├── Misc
│ │ ├── OPMediaPermissionOperation.h
│ │ ├── OPLocationOperation.h
│ │ ├── OPMediaPermissionOperation.m
│ │ └── OPLocationOperation.m
│ │ └── UI
│ │ ├── OPAlertOperation.h
│ │ └── OPAlertOperation.m
│ ├── Core
│ ├── Categories
│ │ ├── NSOperation+Operative.h
│ │ ├── NSMutableDictionary+Operative.h
│ │ ├── NSMutableDictionary+Operative.m
│ │ ├── NSError+Operative.h
│ │ ├── NSError+Operative.m
│ │ └── NSOperation+Operative.m
│ ├── Conditions
│ │ ├── OPOperationConditionEvaluator.h
│ │ ├── OPNoCancelledDependenciesCondition.h
│ │ ├── OPReachabilityCondition.h
│ │ ├── OPNegatedCondition.h
│ │ ├── OPSilentCondition.h
│ │ ├── OPSilentCondition.m
│ │ ├── OPOperationConditionMutuallyExclusive.h
│ │ ├── OPNoCancelledDependenciesCondition.m
│ │ ├── OPOperationConditionMutuallyExclusive.m
│ │ ├── OPOperationConditionEvaluator.m
│ │ ├── OPOperationCondition.h
│ │ ├── OPNegatedCondition.m
│ │ └── OPReachabilityCondition.m
│ ├── Observers
│ │ ├── OPTimeoutObserver.h
│ │ ├── OPOperationObserver.h
│ │ ├── OPBlockObserver.h
│ │ ├── OPBlockObserver.m
│ │ └── OPTimeoutObserver.m
│ ├── Operations
│ │ ├── Misc
│ │ │ ├── OPDelayOperation.h
│ │ │ ├── OPBlockOperation.m
│ │ │ ├── OPDelayOperation.m
│ │ │ ├── OPBlockOperation.h
│ │ │ ├── OPGroupOperation.h
│ │ │ └── OPGroupOperation.m
│ │ ├── Networking
│ │ │ ├── OPURLSessionTaskOperation.h
│ │ │ └── OPURLSessionTaskOperation.m
│ │ └── OPOperation.h
│ └── Operation Queue
│ │ ├── OPExclusivityController.h
│ │ ├── OPOperationQueue.h
│ │ └── OPExclusivityController.m
│ └── Operative.h
├── _Carthage.xcodeproj
├── Example
├── .gitignore
├── Tests
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── Tests-Info.plist
│ ├── Tests.m
│ ├── BlockObserversTests.m
│ └── CategoriesTests.m
├── Operative
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── GroupOperationTest.h
│ ├── Operative-Prefix.pch
│ ├── main.m
│ ├── GroupOperationTest.m
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── OPViewController.h
│ ├── OPAppDelegate.h
│ ├── Main.storyboard
│ ├── Operative-Info.plist
│ ├── OPAppDelegate.m
│ └── OPViewController.m
├── Operative.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Operative-Example.xcscheme
└── Podfile
├── LICENSE
├── .gitignore
├── README.md
├── .travis.yml
└── Operative.podspec
/Pod/Assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Pod/Classes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_Carthage.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------
/Example/.gitignore:
--------------------------------------------------------------------------------
1 | Pods
2 | *.xcworkspace
3 | Podfile.lock
--------------------------------------------------------------------------------
/Example/Tests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/Operative/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/Operative.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Operative/GroupOperationTest.h:
--------------------------------------------------------------------------------
1 | //
2 | // GroupOperationTest.h
3 | // Operative
4 | //
5 | // Created by Tom Wilson on 20/06/2015.
6 | // Copyright (c) 2015 Tom Wilson. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface GroupOperationTest : OPGroupOperation
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | # Cannot use frameworks until min deployment set to 8.0
4 | # use_frameworks!
5 |
6 | target 'Operative_Example', :exclusive => true do
7 | pod "Operative", :path => "../"
8 | end
9 |
10 | target 'Operative_Tests', :exclusive => true do
11 | pod "Operative", :path => "../"
12 | end
13 |
--------------------------------------------------------------------------------
/Example/Operative/Operative-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | @import UIKit;
15 | @import Foundation;
16 | #endif
17 |
--------------------------------------------------------------------------------
/Example/Operative/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Operative
4 | //
5 | // Created by Tom Wilson on 06/16/2015.
6 | // Copyright (c) 2014 Tom Wilson. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 | #import "OPAppDelegate.h"
11 |
12 | int main(int argc, char * argv[])
13 | {
14 | @autoreleasepool {
15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([OPAppDelegate class]));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/Operative/GroupOperationTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // GroupOperationTest.m
3 | // Operative
4 | //
5 | // Created by Tom Wilson on 20/06/2015.
6 | // Copyright (c) 2015 Tom Wilson. All rights reserved.
7 | //
8 |
9 | #import "GroupOperationTest.h"
10 |
11 | @implementation GroupOperationTest
12 |
13 | - (instancetype) init
14 | {
15 | self = [super init];
16 | if (self)
17 | {
18 | OPBlockOperation *block;
19 | for (int i = 0; i < 10; i++)
20 | {
21 | OPBlockOperation *previous = nil;
22 | if (block)
23 | previous = block;
24 |
25 | block = [[OPBlockOperation alloc] initWithBlock:^(void(^completion)(void)) {
26 | NSLog(@"Operation %i", i);
27 | completion();
28 | }];
29 |
30 | if (previous)
31 | {
32 | [block addDependency:previous];
33 | }
34 |
35 | [self addOperation:block];
36 | }
37 | }
38 | return self;
39 | }
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Example/Operative/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "ipad",
20 | "size" : "29x29",
21 | "scale" : "1x"
22 | },
23 | {
24 | "idiom" : "ipad",
25 | "size" : "29x29",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "ipad",
30 | "size" : "40x40",
31 | "scale" : "1x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "40x40",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "76x76",
41 | "scale" : "1x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "76x76",
46 | "scale" : "2x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Tom Wilson
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | # OS X
6 | .DS_Store
7 |
8 | ## Build generated
9 | build/
10 | DerivedData
11 |
12 | ## Various settings
13 | *.pbxuser
14 | !default.pbxuser
15 | *.mode1v3
16 | !default.mode1v3
17 | *.mode2v3
18 | !default.mode2v3
19 | *.perspectivev3
20 | !default.perspectivev3
21 | xcuserdata
22 |
23 | # Bundler
24 | .bundle
25 | .clang-format
26 |
27 | # AppCode
28 | .idea
29 |
30 | ## Other
31 | *.xccheckout
32 | profile
33 | *.moved-aside
34 | *.xcuserstate
35 | *.xcscmblueprint
36 |
37 | ## Obj-C/Swift specific
38 | *.hmap
39 | *.ipa
40 |
41 | # vim
42 | *.swp
43 |
44 | # CocoaPods
45 | #
46 | # We recommend against adding the Pods directory to your .gitignore. However
47 | # you should judge for yourself, the pros and cons are mentioned at:
48 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
49 | #
50 | # Pods/
51 |
52 | # Carthage
53 | #
54 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
55 | # Carthage/Checkouts
56 |
57 | Carthage/Build
58 | Carthage.pkg
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Operative
2 |
3 | [](https://travis-ci.org/Kabal/Operative)
4 | [](http://cocoapods.org/pods/Operative)
5 | [](http://cocoapods.org/pods/Operative)
6 | [](http://cocoapods.org/pods/Operative)
7 |
8 | Objective-C port of the Swift code provided for the WWDC presentation "Advanced NSOperations"
9 |
10 | Not really tested yet.. probably has bugs.
11 |
12 | TODO:
13 | - Not all of the 'Conditions' are ported yet
14 | - Better example app
15 | - Tests!?!
16 |
17 |
18 | ## Usage
19 |
20 | To run the example project, clone the repo, and run `pod install` from the Example directory first.
21 |
22 | ## Requirements
23 |
24 | ## Installation
25 |
26 | Operative is available through [CocoaPods](http://cocoapods.org). To install
27 | it, simply add the following line to your Podfile:
28 |
29 | ```ruby
30 | pod "Operative"
31 | ```
32 |
33 | ## Author
34 |
35 | Tom Wilson, tom@toms-stuff.net
36 |
37 | ## License
38 |
39 | Operative is available under the MIT license. See the LICENSE file for more info.
40 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * http://www.objc.io/issue-6/travis-ci.html
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | language: objective-c
6 | osx_image: beta-xcode6.3
7 | cache: cocoapods
8 | podfile: Example/Podfile
9 | env:
10 | global:
11 | - LC_CTYPE=en.US.UTF-8
12 | - LANG=en_US.UTF_8
13 | matrix:
14 | - DESTINATION="OS=8.3,name=iPhone 6 Plus" SCHEME="Operative-Example" SDK=iphonesimulator8.3 BUILD_EXAMPLE="YES" POD_LINT="YES"
15 | before_install:
16 | - gem install cocoapods # Since Travis is not always on latest version
17 | - pod install --project-directory=Example
18 | install:
19 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
20 | script:
21 | - set -o pipefail
22 | - if [ $BUILD_EXAMPLE == "YES" ]; then
23 | xcodebuild -workspace "Example/Operative.xcworkspace" -scheme "Operative-Example" -sdk "$SDK" -destination "$DESTINATION"
24 | -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c;
25 | fi
26 | - if [ $BUILD_EXAMPLE == "YES" ]; then
27 | xcodebuild -workspace "Example/Operative.xcworkspace" -scheme "Operative-Example" -sdk "$SDK" -destination "$DESTINATION"
28 | -configuration Release ONLY_ACTIVE_ARCH=NO test | xcpretty -c;
29 | fi
30 | - if [ $POD_LINT == "YES" ]; then
31 | pod lib lint --quick;
32 | fi
33 |
--------------------------------------------------------------------------------
/Example/Operative/OPViewController.h:
--------------------------------------------------------------------------------
1 | // OPViewController.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | @import UIKit;
23 |
24 | @interface OPViewController : UIViewController
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Example/Tests/Tests.m:
--------------------------------------------------------------------------------
1 | // OperativeTests.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 | @interface Tests : XCTestCase
25 |
26 | @end
27 |
28 | @implementation Tests
29 |
30 | @end
--------------------------------------------------------------------------------
/Example/Operative/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | },
18 | {
19 | "orientation" : "portrait",
20 | "idiom" : "ipad",
21 | "extent" : "full-screen",
22 | "minimum-system-version" : "7.0",
23 | "scale" : "1x"
24 | },
25 | {
26 | "orientation" : "landscape",
27 | "idiom" : "ipad",
28 | "extent" : "full-screen",
29 | "minimum-system-version" : "7.0",
30 | "scale" : "1x"
31 | },
32 | {
33 | "orientation" : "portrait",
34 | "idiom" : "ipad",
35 | "extent" : "full-screen",
36 | "minimum-system-version" : "7.0",
37 | "scale" : "2x"
38 | },
39 | {
40 | "orientation" : "landscape",
41 | "idiom" : "ipad",
42 | "extent" : "full-screen",
43 | "minimum-system-version" : "7.0",
44 | "scale" : "2x"
45 | }
46 | ],
47 | "info" : {
48 | "version" : 1,
49 | "author" : "xcode"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Example/Operative/OPAppDelegate.h:
--------------------------------------------------------------------------------
1 | // OPAppDelegate.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | @import UIKit;
23 |
24 | @interface OPAppDelegate : UIResponder
25 |
26 | @property (strong, nonatomic) UIWindow *window;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPPhotosCondition.h:
--------------------------------------------------------------------------------
1 | // OPPhotosCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 | /**
25 | * A condition for verifying access to the user's Photos library.
26 | */
27 | @interface OPPhotosCondition : NSObject
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPAudioCondition.h:
--------------------------------------------------------------------------------
1 | // OPAudioCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 | /**
25 | * A condition for verifying microphone permission using AVMediaTypeAudio
26 | */
27 | @interface OPAudioCondition : NSObject
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPVideoCondition.h:
--------------------------------------------------------------------------------
1 | // OPVideoCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | #import "OPOperationCondition.h"
24 |
25 | /**
26 | * A condition for verifying camera permission using AVMediaTypeVideo.
27 | */
28 | @interface OPVideoCondition : NSObject
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Categories/NSOperation+Operative.h:
--------------------------------------------------------------------------------
1 | // NSOperation+Operative.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 |
25 | @interface NSOperation (Operative)
26 |
27 | - (void)addCompletionBlock:(void (^)(void))block;
28 |
29 | - (void)addDependencies:(NSArray *)dependencies;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Categories/NSMutableDictionary+Operative.h:
--------------------------------------------------------------------------------
1 | // NSMutableDictionary+Operative.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 |
25 | @interface NSMutableDictionary (Operative)
26 |
27 | + (NSMutableDictionary *)sequence:(id )sequence keyMapper:(id (^)(id obj))keyMapper;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Observers/OPNetworkObserver.h:
--------------------------------------------------------------------------------
1 | // OPNetworkObserver.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationObserver.h"
23 |
24 |
25 | /**
26 | * An `OPOperationObserver` that will cause the network activity indicator
27 | * to appear as long as the `OPOperation` to which it is attached is executing.
28 | */
29 | @interface OPNetworkObserver : NSObject
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPOperationConditionEvaluator.h:
--------------------------------------------------------------------------------
1 | // OPOperationConditionEvaluator.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 |
25 | @interface OPOperationConditionEvaluator : NSObject
26 |
27 | + (void)evaluateConditions:(NSArray *)conditions
28 | operation:(OPOperation *)operation
29 | completion:(void (^)(NSArray *failures))completion;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPNoCancelledDependenciesCondition.h:
--------------------------------------------------------------------------------
1 | // OPNoCancelledDependenciesCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 | /**
25 | * A condition that specifies that every dependency must have succeeded.
26 | * If any dependency was cancelled, the target operation will be cancelled as
27 | * well.
28 | */
29 | @interface OPNoCancelledDependenciesCondition : NSObject
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Categories/UIUserNotificationSettings+Operative.h:
--------------------------------------------------------------------------------
1 | // UIUserNotificationSettings+Operative.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | #if TARGET_OS_IPHONE
24 |
25 | #import
26 |
27 |
28 | @interface UIUserNotificationSettings (Operative)
29 |
30 | - (BOOL)containsSettings:(UIUserNotificationSettings *)settings;
31 |
32 | - (UIUserNotificationSettings *)settingsByMerging:(UIUserNotificationSettings *)settings;
33 |
34 | @end
35 |
36 | #endif
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Operations/Misc/OPMediaPermissionOperation.h:
--------------------------------------------------------------------------------
1 | // OPMediaPermissionOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 | /**
25 | * `OPMediaPermissionOperation` is an `OPOperation` subclass to request
26 | * permission to use the device's video or audio media type.
27 | *
28 | - returns: An instance of `OPMediaPermissionOperation`
29 | */
30 | @interface OPMediaPermissionOperation : OPOperation
31 |
32 | - (instancetype)initWithMediaType:(NSString *)mediaType NS_DESIGNATED_INITIALIZER;
33 |
34 | - (instancetype)init NS_UNAVAILABLE;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Example/Operative/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Categories/NSMutableDictionary+Operative.m:
--------------------------------------------------------------------------------
1 | // NSMutableDictionary+Operative.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "NSMutableDictionary+Operative.h"
23 |
24 |
25 | @implementation NSMutableDictionary (Operative)
26 |
27 | + (NSMutableDictionary *)sequence:(id )sequence keyMapper:(id (^)(id obj))keyMapper
28 | {
29 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
30 | for (id obj in sequence) {
31 | id key = keyMapper(obj);
32 | if (key) {
33 | dict[key] = obj;
34 | }
35 | }
36 | return dict;
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Observers/OPTimeoutObserver.h:
--------------------------------------------------------------------------------
1 | // OPTimeoutObserver.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationObserver.h"
23 |
24 |
25 | /**
26 | * `OPTimeoutObserver` is a way to make an `OPOperation` automatically
27 | * time out and cancel after a specified time interval.
28 | *
29 | * - returns: An instance of an `OPTimeoutObserver`
30 | */
31 | @interface OPTimeoutObserver : NSObject
32 |
33 | - (instancetype)initWithTimeout:(NSTimeInterval)timeout NS_DESIGNATED_INITIALIZER;
34 |
35 | /**
36 | * Unused `-init` method.
37 | * @see -initWithTimeout:
38 | */
39 | - (instancetype)init NS_UNAVAILABLE;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Observers/OPBackgroundObserver.h:
--------------------------------------------------------------------------------
1 | // OPBackgroundObserver.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 | #import "OPOperationObserver.h"
25 |
26 |
27 | /**
28 | * `OPBackgroundObserver` is an `OPOperationObserver` that will automatically begin
29 | * and end a background task if the application transitions to the background.
30 | * This would be useful if you had a vital `OPOperation` whose execution *must* complete,
31 | * regardless of the activation state of the app. Some kinds network connections
32 | * may fall in to this category, for example.
33 | */
34 | @interface OPBackgroundObserver : NSObject
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Categories/NSError+Operative.h:
--------------------------------------------------------------------------------
1 | // NSError+Operative.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 |
25 | extern NSString *const kOPOperationErrorDomain;
26 | extern NSString *const kOPOperationConditionKey;
27 | extern NSString *const kOPOperationNegatedConditionKey;
28 |
29 | typedef NS_ENUM(NSUInteger, OPOperationErrorCode) {
30 | OPOperationErrorCodeConditionFailed = 1,
31 | OPOperationErrorCodeExecutionFailed
32 | };
33 |
34 |
35 | @interface NSError (Operative)
36 |
37 | + (instancetype)errorWithCode:(OPOperationErrorCode)code;
38 |
39 | + (instancetype)errorWithCode:(OPOperationErrorCode)code userInfo:(NSDictionary *)userInfo;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Example/Operative/Operative-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | NSLocationWhenInUseUsageDescription
28 | Tracking your every waking movement.
29 | UIMainStoryboardFile
30 | Main
31 | UIMainStoryboardFile~ipad
32 | Main_iPad
33 | UIRequiredDeviceCapabilities
34 |
35 | armv7
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | UISupportedInterfaceOrientations~ipad
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationPortraitUpsideDown
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Categories/NSError+Operative.m:
--------------------------------------------------------------------------------
1 | // NSError+Operative.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "NSError+Operative.h"
23 |
24 |
25 | NSString *const kOPOperationErrorDomain = @"OPOperationErrors";
26 | NSString *const kOPOperationConditionKey = @"OPOperationCondition";
27 | NSString *const kOPOperationNegatedConditionKey = @"OPOperationNegatedCondition";
28 |
29 |
30 | @implementation NSError (Operative)
31 |
32 | + (instancetype)errorWithCode:(OPOperationErrorCode)code
33 | {
34 | return [NSError errorWithCode:code userInfo:nil];
35 | }
36 |
37 | + (instancetype)errorWithCode:(OPOperationErrorCode)code userInfo:(NSDictionary *)userInfo
38 | {
39 | return [NSError errorWithDomain:kOPOperationErrorDomain code:code userInfo:userInfo];
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPReachabilityCondition.h:
--------------------------------------------------------------------------------
1 | // OPReachabilityCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 |
25 | /**
26 | * This is a condition that performs a very high-level reachability check.
27 | * It does *not* perform a long-running reachability check, nor does it
28 | * respond to changes in reachability. Reachability is evaluated once when
29 | * the operation to which this is attached is asked about its readiness.
30 | */
31 | @interface OPReachabilityCondition : NSObject
32 |
33 | - (instancetype)initWithHost:(NSURL *)host NS_DESIGNATED_INITIALIZER;
34 |
35 | /**
36 | * Unused `-init` method.
37 | * @see -initWithHost:
38 | */
39 | - (instancetype)init NS_UNAVAILABLE;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Observers/OPOperationObserver.h:
--------------------------------------------------------------------------------
1 | // OPOperationObserver.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 | @class OPOperation;
25 |
26 | @protocol OPOperationObserver
27 |
28 | // Invoked immediately prior to the `OPOperation`'s `-execute` method.
29 | - (void)operationDidStart:(OPOperation *)operation;
30 |
31 | // Invoked when `OPOperation`'s `-produceOperation:` is executed.
32 | - (void)operation:(OPOperation *)operation didProduceOperation:(NSOperation *)newOperation;
33 |
34 | /**
35 | * Invoked as an `OPOperation` finishes, along with any errors produced during
36 | * execution (or readiness evaluation).
37 | */
38 | - (void)operation:(OPOperation *)operation didFinishWithErrors:(NSArray *)errors;
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Categories/NSOperation+Operative.m:
--------------------------------------------------------------------------------
1 | // NSOperation+Operative.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "NSOperation+Operative.h"
23 |
24 |
25 | @implementation NSOperation (Operative)
26 |
27 | - (void)addCompletionBlock:(void (^)(void))block
28 | {
29 | // If we already have a completion block
30 | if ([self completionBlock]) {
31 | // Construct a new block that calls the existing block
32 | void (^existing)(void) = [self.completionBlock copy];
33 |
34 | self.completionBlock = ^{
35 | existing();
36 | block();
37 | };
38 | } else {
39 | [self setCompletionBlock:block];
40 | }
41 | }
42 |
43 | - (void)addDependencies:(NSArray *)dependencies
44 | {
45 | for (NSOperation *dependency in dependencies) {
46 | [self addDependency:dependency];
47 | }
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Operative.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint Operative.podspec' to ensure this is a
3 | # valid spec and remove all comments before submitting the spec.
4 | #
5 | # Any lines starting with a # are optional, but encouraged
6 | #
7 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
8 | #
9 |
10 | Pod::Spec.new do |s|
11 | s.name = "Operative"
12 | s.version = "0.1.0"
13 | s.summary = "Advanced NSOperations. Objective-C Port of the sample code in the Apple WWDC 2015 presentation \"Advanced NSOperations\""
14 | s.description = <<-DESC
15 |
16 | Provides a NSOperation sublass with a more advanced state machine.
17 |
18 | Some features provided:
19 | - Easily perform asynchronous 'work' in an operation - even displaying UI such as UIAlertController's
20 | - Optionally support 'exclusiviity' guarantees across mulitple instances of the same operation class, even across multiple queues!
21 | - Operation delegate - be informed when an operation starts, finishes, or produces sub-operations
22 |
23 | DESC
24 | s.homepage = "https://github.com/Kabal/Operative"
25 | # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
26 | s.license = 'MIT'
27 | s.author = { "Tom Wilson" => "tom@toms-stuff.net" }
28 | s.source = { :git => "https://github.com/Kabal/Operative.git", :tag => s.version.to_s }
29 | s.social_media_url = 'https://twitter.com/tomwilson'
30 |
31 | s.ios.deployment_target = '8.0'
32 | s.osx.deployment_target = '10.10'
33 | s.requires_arc = true
34 |
35 | s.source_files = 'Pod/Classes/Operative.h'
36 | s.ios.source_files = 'Pod/Classes/{Core,iOS}/**/*'
37 | s.osx.source_files = 'Pod/Classes/{Core,OSX}/**/*'
38 |
39 | # s.public_header_files = 'Pod/Classes/**/*.h'
40 |
41 | s.ios.frameworks = 'UIKit', 'AVFoundation'
42 |
43 | # s.dependency 'AFNetworking', '~> 2.3'
44 | end
45 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Operations/Misc/OPLocationOperation.h:
--------------------------------------------------------------------------------
1 | // OPLocationOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | #import "OPOperation.h"
24 |
25 | #import
26 |
27 |
28 | /**
29 | * `OPLocationOperation` is an `OPOperation` subclass to do a "one-shot"
30 | * request to get the user's current location, with a desired accuracy.
31 | * This operation will prompt for `WhenInUse` location authorization,
32 | * if the app does not already have it.
33 | *
34 | * - returns: An instance of `OPLocationOperation`
35 | */
36 | @interface OPLocationOperation : OPOperation
37 |
38 | - (instancetype)initWithAccuracy:(CLLocationAccuracy)accuracy
39 | locationHandler:(void (^)(CLLocation *location))locationHandler NS_DESIGNATED_INITIALIZER;
40 |
41 | /**
42 | * Unused `-init` method.
43 | * @see -initWithAccuracy:locationHandler:
44 | */
45 | - (instancetype)init NS_UNAVAILABLE;
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPNegatedCondition.h:
--------------------------------------------------------------------------------
1 | // OPNegatedCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 |
25 | NS_ASSUME_NONNULL_BEGIN
26 |
27 |
28 | /**
29 | * A simple condition that negates the evaluation of another condition.
30 | * This is useful (for example) if you want to only execute an operation if the
31 | * network is NOT reachable.
32 | */
33 | @interface OPNegatedCondition : NSObject
34 |
35 | /**
36 | * Initializes an `OPNegatedCondition` object with the provided condition.
37 | *
38 | * This is the designated initializer.
39 | *
40 | * @param condition The condition which should be negated.
41 | *
42 | * @return The newly-initialized `OPNegatedCondition`
43 | */
44 | - (instancetype)initWithCondition:(id )condition NS_DESIGNATED_INITIALIZER;
45 |
46 | /**
47 | * Unused `-init` method.
48 | * @see - initWithCondition:
49 | */
50 | - (instancetype)init NS_UNAVAILABLE;
51 |
52 | @end
53 |
54 | NS_ASSUME_NONNULL_END
55 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPLocationCondition.h:
--------------------------------------------------------------------------------
1 | // OPLocationCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 |
25 | typedef NS_ENUM(NSUInteger, OPLocationConditionUsage) {
26 | OPLocationConditionWhenInUse,
27 | OPLocationConditionAlways,
28 | };
29 |
30 |
31 | /**
32 | * A condition for verifying access to the user's location.
33 | *
34 | * - returns: An `NSObject` conforming to the `OPOperationCondition` protocol
35 | */
36 | @interface OPLocationCondition : NSObject
37 |
38 | /**
39 | * Designated initializer, otherwise calling `-init` will return an
40 | * `OPLocationCondition` with a default usage of
41 | * `OPLocationConditionWhenInUse`.
42 | *
43 | * @param usage A value defining the required location usage permission in
44 | * order to satisfy the condition.
45 | *
46 | * @return An `OPLocationCondition` object with the required location usage
47 | * permission defined.
48 | */
49 | - (instancetype)initWithUsage:(OPLocationConditionUsage)usage NS_DESIGNATED_INITIALIZER;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Observers/OPBlockObserver.h:
--------------------------------------------------------------------------------
1 | // OPBlockObserver.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationObserver.h"
23 |
24 |
25 | /**
26 | * The `OPBlockObserver` is a way to attach arbitrary blocks to significant
27 | * events in an `OPOperation`'s lifecycle.
28 | */
29 | @interface OPBlockObserver : NSObject
30 |
31 | @property (copy, nonatomic) void (^startHandler)(OPOperation *operation);
32 |
33 | @property (copy, nonatomic) void (^produceHander)(OPOperation *operation, NSOperation *newOperation);
34 |
35 | @property (copy, nonatomic) void (^finishHandler)(OPOperation *operation, NSArray *errors);
36 |
37 | - (instancetype)initWithStartHandler:(void (^)(OPOperation *operation))startHandler
38 | produceHandler:(void (^)(OPOperation *operation, NSOperation *newOperation))produceHandler
39 | finishHandler:(void (^)(OPOperation *operation, NSArray *errors))finishHandler NS_DESIGNATED_INITIALIZER;
40 |
41 | - (instancetype)initWithFinishHandler:(void(^)(OPOperation *operation, NSArray *errors))finishHandler;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPSilentCondition.h:
--------------------------------------------------------------------------------
1 | // OPSilentCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 |
25 | NS_ASSUME_NONNULL_BEGIN
26 |
27 | /**
28 | * A simple condition that causes another condition to not enqueue its
29 | * dependency. This is useful (for example) when you want to verify that you
30 | * have access to the user's location, but you do not want to prompt them for
31 | * permission if you do not already have it.
32 | */
33 | @interface OPSilentCondition : NSObject
34 |
35 | /**
36 | * Initializes an `OPSilentCondition` object with the provided condition.
37 | *
38 | * This is the designated initializer.
39 | *
40 | * @param condition The condition which should be silent.
41 | *
42 | * @return The newly-initialized `OPSilentCondition`
43 | */
44 | - (instancetype)initWithCondition:(id )condition NS_DESIGNATED_INITIALIZER;
45 |
46 | /**
47 | * Unused `-init` method.
48 | * @see -initWithCondition:
49 | */
50 | - (instancetype)init NS_UNAVAILABLE;
51 |
52 | @end
53 |
54 | NS_ASSUME_NONNULL_END
55 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Misc/OPDelayOperation.h:
--------------------------------------------------------------------------------
1 | // OPDelayOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 | /**
25 | * `OPDelayOperation` is an `OPOperation` that will simply wait for a given time
26 | * interval, or until a specific `NSDate`.
27 | *
28 | * It is important to note that this operation does **not** use the `sleep()`
29 | * function, since that is inefficient and blocks the thread on which it is called.
30 | * Instead, this operation uses `dispatch_after` to know when the appropriate amount
31 | * of time has passed.
32 | *
33 | * If the interval is negative, or the `NSDate` is in the past, then this operation
34 | * immediately finishes.
35 | *
36 | * - returns: An instance of an `OPDelayOperation`
37 | */
38 | @interface OPDelayOperation : OPOperation
39 |
40 | - (instancetype)initWithTimeInterval:(NSTimeInterval)interval NS_DESIGNATED_INITIALIZER;
41 |
42 | - (instancetype)initWithDate:(NSDate *)date;
43 |
44 | /**
45 | * Unused `-init` method.
46 | * @see -initWithTimeInterval:
47 | * @see -initWithDate:
48 | */
49 | - (instancetype)init NS_UNAVAILABLE;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPOperationConditionUserNotification.h:
--------------------------------------------------------------------------------
1 | // OPOperationConditionUserNotification.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #if TARGET_OS_IPHONE
23 |
24 | #import
25 | #import "OPOperationCondition.h"
26 |
27 | typedef NS_ENUM(NSUInteger, OPOperationConditionUserNotificationBehavior) {
28 | OPOperationConditionBehaviorMerge,
29 | OPOperationConditionBehaviorReplace,
30 | };
31 |
32 | extern NSString * const kCurrentSettings;
33 | extern NSString * const kDesiredSettings;
34 |
35 | @interface OPOperationConditionUserNotification : NSObject
36 |
37 | - (instancetype)initWithSettings:(UIUserNotificationSettings *)settings
38 | application:(UIApplication *)application
39 | behavior:(OPOperationConditionUserNotificationBehavior)behavior NS_DESIGNATED_INITIALIZER;
40 |
41 | - (instancetype)initWithSettings:(UIUserNotificationSettings *)settings application:(UIApplication *)application;
42 |
43 | /**
44 | * Unused `-init` method.
45 | * @see -initWithSettings:application:behavior
46 | */
47 | - (instancetype)init NS_UNAVAILABLE;
48 |
49 | @end
50 |
51 | #endif
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPRemoteNotificationCondition.h:
--------------------------------------------------------------------------------
1 | // OPRemoteNotificationCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 |
25 | /**
26 | * A condition for verifying that the app has the ability to receive push notifications.
27 | */
28 | @interface OPRemoteNotificationCondition : NSObject
29 |
30 | /**
31 | * Class method called upon by `UIApplication` when a remote notification
32 | * push token has been received.
33 | * Either this method or -didFailToRegister: should be called during
34 | * the remote notification registration process.
35 | *
36 | * @param token `NSData` object received upon successful remote notification registration
37 | */
38 | + (void)didReceiveNotificationToken:(NSData *)token;
39 |
40 | /**
41 | * Class method called upon by `UIApplication` when a remote notification
42 | * registration process failed with an error.
43 | * Either this method or -didReceiveNotificationToken: should be called during
44 | * the remote notification registration process.
45 | *
46 | * @param error `NSError` object describing the failed registration
47 | */
48 | + (void)didFailToRegister:(NSError *)error;
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Misc/OPBlockOperation.m:
--------------------------------------------------------------------------------
1 | // OPBlockOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPBlockOperation.h"
23 |
24 |
25 | @interface OPBlockOperation ()
26 |
27 | @property (copy, nonatomic) OPOperationBlock block;
28 |
29 | @end
30 |
31 | @implementation OPBlockOperation
32 |
33 |
34 | #pragma mark - Overrides
35 | #pragma mark -
36 |
37 | - (void)execute
38 | {
39 | if ([self block]) {
40 | self.block(^{
41 | [self finish];
42 | });
43 | } else {
44 | [self finish];
45 | }
46 | }
47 |
48 |
49 | #pragma mark - Lifecycle
50 | #pragma mark -
51 |
52 | - (instancetype)initWithBlock:(OPOperationBlock)block
53 | {
54 | self = [super init];
55 | if (!self) {
56 | return nil;
57 | }
58 |
59 | _block = [block copy];
60 |
61 | return self;
62 | }
63 |
64 | - (instancetype)initWithMainQueueBlock:(void (^)(void))mainQueueBlock
65 | {
66 | OPOperationBlock block = ^(void(^continuation)()) {
67 | dispatch_async(dispatch_get_main_queue(), ^{
68 | mainQueueBlock();
69 | continuation();
70 | });
71 | };
72 |
73 | return [self initWithBlock:block];
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/Pod/Classes/Operative.h:
--------------------------------------------------------------------------------
1 | // Operative.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #ifndef Pods_Operative_h
23 | #define Pods_Operative_h
24 |
25 | // Core
26 | #import "OPOperation.h"
27 | #import "OPOperationQueue.h"
28 | #import "OPOperationObserver.h"
29 |
30 | // Operations
31 | #import "OPBlockOperation.h"
32 | #import "OPURLSessionTaskOperation.h"
33 | #import "OPGroupOperation.h"
34 | #import "OPDelayOperation.h"
35 |
36 | #if TARGET_OS_IPHONE
37 | #import "OPMediaPermissionOperation.h"
38 | #import "OPLocationOperation.h"
39 | #import "OPAlertOperation.h"
40 | #endif
41 |
42 | // Conditions
43 | #import "OPOperationConditionMutuallyExclusive.h"
44 | #import "OPReachabilityCondition.h"
45 |
46 | #if TARGET_OS_IPHONE
47 | #import "OPLocationCondition.h"
48 | #import "OPOperationConditionUserNotification.h"
49 | #import "OPPhotosCondition.h"
50 | #import "OPRemoteNotificationCondition.h"
51 | #import "OPVideoCondition.h"
52 | #import "OPAudioCondition.h"
53 | #endif
54 |
55 | #import "OPSilentCondition.h"
56 | #import "OPNoCancelledDependenciesCondition.h"
57 |
58 | // Observers
59 | #import "OPBlockObserver.h"
60 | #import "OPTimeoutObserver.h"
61 |
62 | #if TARGET_OS_IPHONE
63 | #import "OPBackgroundObserver.h"
64 | #import "OPNetworkObserver.h"
65 | #endif
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operation Queue/OPExclusivityController.h:
--------------------------------------------------------------------------------
1 | // OPExclusivityController.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 | #import "OPOperation.h"
24 |
25 |
26 | /**
27 | * `OPExclusivityController` is a singleton to keep track of all the in-flight
28 | * `OPOperation` instances that have declared themselves as requiring mutual exclusivity.
29 | * We use a singleton because mutual exclusivity must be enforced across the entire
30 | * app, regardless of the `OPOperationQueue` on which an `OPOperation` was executed.
31 | */
32 | @interface OPExclusivityController : NSObject
33 |
34 | + (OPExclusivityController *)sharedExclusivityController;
35 |
36 | /**
37 | * Registers an operation as being mutually exclusive
38 | *
39 | * @param operation OPOperation object which requires exclusivity
40 | * @param categories Array of strings describing the name of the category of exclusivity
41 | */
42 | - (void)addOperation:(OPOperation *)operation categories:(NSArray *)categories;
43 |
44 | /**
45 | * Unregisters an operation from being mutually exclusive.
46 | *
47 | * @param operation OPOperation object which requires exclusivity
48 | * @param categories Array of strings describing the name of the category of exclusivity
49 | */
50 | - (void)removeOperation:(OPOperation *)operation categories:(NSArray *)categories;
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Operations/Misc/OPMediaPermissionOperation.m:
--------------------------------------------------------------------------------
1 | // OPMediaPermissionOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | @import AVFoundation;
23 |
24 | #import "OPMediaPermissionOperation.h"
25 | #import "OPOperationConditionMutuallyExclusive.h"
26 |
27 | @interface OPMediaPermissionOperation()
28 |
29 | @property (copy, nonatomic) NSString *mediaType;
30 |
31 | @end
32 |
33 | @implementation OPMediaPermissionOperation
34 |
35 | #pragma mark - Lifecycle
36 | #pragma mark -
37 |
38 | - (instancetype)initWithMediaType:(NSString *)mediaType
39 | {
40 | self = [super init];
41 | if (!self) {
42 | return nil;
43 | }
44 |
45 | _mediaType = [mediaType copy];
46 |
47 | [self addCondition:[OPOperationConditionMutuallyExclusive alertPresentationExclusivity]];
48 |
49 | return self;
50 | }
51 |
52 | #pragma mark - Overrides
53 | #pragma mark -
54 |
55 | - (void)execute
56 | {
57 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:[self mediaType]];
58 | if (status == AVAuthorizationStatusNotDetermined) {
59 | dispatch_async(dispatch_get_main_queue(), ^{
60 | [AVCaptureDevice requestAccessForMediaType:[self mediaType] completionHandler:^(BOOL granted) {
61 | [self finish];
62 | }];
63 | });
64 | } else {
65 | [self finish];
66 | }
67 | }
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPSilentCondition.m:
--------------------------------------------------------------------------------
1 | // OPSilentCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | #import "OPSilentCondition.h"
24 |
25 |
26 | @interface OPSilentCondition ()
27 |
28 | /**
29 | * Underlying condition which is evaluated.
30 | */
31 | @property (strong, nonatomic, readonly) id condition;
32 |
33 | @end
34 |
35 |
36 | @implementation OPSilentCondition
37 |
38 |
39 | #pragma mark - Lifecycle
40 | #pragma mark -
41 |
42 | - (instancetype)initWithCondition:(id )condition
43 | {
44 | self = [super init];
45 |
46 | _condition = condition;
47 |
48 | return self;
49 | }
50 |
51 |
52 | #pragma mark - OPOperationCondition Protocol
53 | #pragma mark -
54 |
55 | - (NSString *)name
56 | {
57 | return [NSString stringWithFormat:@"Silent<%@>", [self.condition name]];
58 | }
59 |
60 | - (BOOL)isMutuallyExclusive
61 | {
62 | return [self.condition isMutuallyExclusive];
63 | }
64 |
65 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
66 | {
67 | return nil;
68 | }
69 |
70 | - (void)evaluateConditionForOperation:(OPOperation *)operation
71 | completion:(void (^)(OPOperationConditionResultStatus result, NSError *error))completion
72 | {
73 | [self.condition evaluateConditionForOperation:operation
74 | completion:completion];
75 | }
76 |
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Misc/OPDelayOperation.m:
--------------------------------------------------------------------------------
1 | // OPDelayOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPDelayOperation.h"
23 |
24 |
25 | @interface OPDelayOperation ()
26 |
27 | @property (assign, nonatomic) NSTimeInterval delay;
28 |
29 | @end
30 |
31 |
32 | @implementation OPDelayOperation
33 |
34 |
35 | #pragma mark - Overrides
36 | #pragma mark -
37 |
38 | - (void)execute
39 | {
40 | if ([self delay] < 0) {
41 | [self finish];
42 | return;
43 | }
44 |
45 | dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)([self delay] * NSEC_PER_SEC));
46 |
47 | dispatch_after(when, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
48 | // If we were cancelled, then -finish has already been called.
49 | if (![self isCancelled]) {
50 | [self finish];
51 | }
52 | });
53 | }
54 |
55 | - (void)cancel
56 | {
57 | [super cancel];
58 | // Cancelling the operation means we don't want to wait anymore.
59 | [self finish];
60 | }
61 |
62 |
63 | #pragma mark - Lifecycle
64 | #pragma mark -
65 |
66 | - (instancetype)initWithTimeInterval:(NSTimeInterval)interval
67 | {
68 | self = [super init];
69 | if (!self) {
70 | return nil;
71 | }
72 |
73 | _delay = interval;
74 |
75 | return self;
76 | }
77 |
78 | - (instancetype)initWithDate:(NSDate *)date
79 | {
80 | return [self initWithTimeInterval:[date timeIntervalSinceNow]];
81 | }
82 |
83 | @end
84 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPAudioCondition.m:
--------------------------------------------------------------------------------
1 | // OPAudioCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | @import AVFoundation;
23 |
24 | #import "OPAudioCondition.h"
25 | #import "OPMediaPermissionOperation.h"
26 |
27 | #import "NSError+Operative.h"
28 |
29 | @implementation OPAudioCondition
30 |
31 | #pragma mark - OPOperationCondition Protocol
32 | #pragma mark -
33 |
34 | - (NSString *)name
35 | {
36 | return @"Audio";
37 | }
38 |
39 | - (BOOL)isMutuallyExclusive
40 | {
41 | return NO;
42 | }
43 |
44 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
45 | {
46 | return [[OPMediaPermissionOperation alloc] initWithMediaType:AVMediaTypeAudio];
47 | }
48 |
49 | - (void)evaluateConditionForOperation:(OPOperation *)operation completion:(void (^)(OPOperationConditionResultStatus, NSError *))completion
50 | {
51 | NSArray *availableDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
52 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
53 |
54 | if (status == AVAuthorizationStatusAuthorized || [availableDevices count] == 0) {
55 | completion(OPOperationConditionResultStatusSatisfied, nil);
56 | } else {
57 | NSDictionary *userInfo = @{ kOPOperationConditionKey : [self name] };
58 | NSError *error = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:userInfo];
59 | completion(OPOperationConditionResultStatusFailed, error);
60 | }
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPVideoCondition.m:
--------------------------------------------------------------------------------
1 | // OPVideoCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | @import AVFoundation;
23 |
24 | #import "OPVideoCondition.h"
25 | #import "OPMediaPermissionOperation.h"
26 |
27 | #import "NSError+Operative.h"
28 |
29 | @implementation OPVideoCondition
30 |
31 | #pragma mark - OPOperationCondition Protocol
32 | #pragma mark -
33 |
34 | - (NSString *)name
35 | {
36 | return @"Video";
37 | }
38 |
39 | - (BOOL)isMutuallyExclusive
40 | {
41 | return NO;
42 | }
43 |
44 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
45 | {
46 | return [[OPMediaPermissionOperation alloc] initWithMediaType:AVMediaTypeVideo];
47 | }
48 |
49 | - (void)evaluateConditionForOperation:(OPOperation *)operation completion:(void (^)(OPOperationConditionResultStatus, NSError *))completion
50 | {
51 | NSArray *availableDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
52 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
53 |
54 | if (status == AVAuthorizationStatusAuthorized || [availableDevices count] == 0) {
55 | completion(OPOperationConditionResultStatusSatisfied, nil);
56 | } else {
57 | NSDictionary *userInfo = @{ kOPOperationConditionKey : [self name] };
58 | NSError *error = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:userInfo];
59 | completion(OPOperationConditionResultStatusFailed, error);
60 | }
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Operations/UI/OPAlertOperation.h:
--------------------------------------------------------------------------------
1 | // OPAlertOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #if TARGET_OS_IPHONE
23 |
24 | #import "OPOperation.h"
25 |
26 | #import
27 |
28 |
29 | @interface OPAlertOperation : OPOperation
30 |
31 | /**
32 | * Initializes an instance of OPAlertOperation with the contained
33 | * UIAlertController's UIAlertControllerStyle defaulted to
34 | * UIAlertControllerStyleActionSheet
35 | *
36 | * @see -initWithPresentationContext:preferredStyle
37 | *
38 | * @param presentationContext UIViewController from which the UIAlertController
39 | * will be present. If nil then this will default to
40 | * the rootViewController of the sharedApplication.
41 | *
42 | * @return An initialized OPAlertOperation
43 | */
44 | - (instancetype)initWithPresentationContext:(UIViewController *)presentationContext;
45 |
46 | - (instancetype)initWithPresentationContext:(UIViewController *)presentationContext
47 | preferredStyle:(UIAlertControllerStyle)preferredStyle NS_DESIGNATED_INITIALIZER;
48 |
49 | /**
50 | * Unused `-init` method.
51 | * @see -initWithPresentationContext:
52 | */
53 | - (instancetype)init NS_UNAVAILABLE;
54 |
55 | @property (copy, nonatomic) NSString *title;
56 |
57 | @property (copy, nonatomic) NSString *message;
58 |
59 | - (void)addAction:(NSString *)title
60 | style:(UIAlertActionStyle)style
61 | handler:(void (^)(OPAlertOperation *alertOperation))handler;
62 |
63 | @end
64 |
65 | #endif
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPOperationConditionMutuallyExclusive.h:
--------------------------------------------------------------------------------
1 | // OPOperationConditionMutuallyExclusive.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationCondition.h"
23 |
24 |
25 | @interface OPOperationConditionMutuallyExclusive : NSObject
26 |
27 | + (OPOperationConditionMutuallyExclusive *)mutuallyExclusiveWith:(Class)cls;
28 |
29 | /**
30 | * Class method that returns a mutually exclusive condition for a target
31 | * operation that may present an alert.
32 | *
33 | * @return `OPOperationConditionMutuallyExclusive` object with class of type
34 | * `OPAlertPresentation`
35 | *
36 | * @see OPAlertPresentation
37 | */
38 | + (OPOperationConditionMutuallyExclusive *)alertPresentationExclusivity;
39 |
40 | - (instancetype)initWithClass:(Class)cls NS_DESIGNATED_INITIALIZER;
41 |
42 | /**
43 | * Unused `-init` method.
44 | * @see -initWithClass:
45 | */
46 | - (instancetype)init NS_UNAVAILABLE;
47 |
48 | @end
49 |
50 | /**
51 | * Provides a simple class for usage in defining exclusivity for a target that
52 | * may display an alert (via system, `UIAlertController`, `UIAlertView`, etc.)
53 | *
54 | * When defining an operation with an alert view mutually exclusivity
55 | * condition, always use this class as opposed to `[UIAlertController class]`
56 | * or `[UIAlertView class]`.
57 | *
58 | * For simplicity, `OPOperationConditionMutuallyExclusive` has a class method
59 | * `+alertPresentationExclusivity` which returns a mutually exclusive condition
60 | * setup with `[OPAlertPresentation class]`
61 | *
62 | * @see alertPresentationExclusivity
63 | */
64 | @interface OPAlertPresentation : NSObject
65 | @end
66 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPNoCancelledDependenciesCondition.m:
--------------------------------------------------------------------------------
1 | // OPNoCancelledDependenciesCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPNoCancelledDependenciesCondition.h"
23 | #import "NSError+Operative.h"
24 |
25 | NSString * const kOPCancelledDependenciesKey = @"CancelledDependencies";
26 |
27 | @implementation OPNoCancelledDependenciesCondition
28 |
29 | - (BOOL)isMutuallyExclusive {
30 | return NO;
31 | }
32 |
33 | - (NSString *)name {
34 | return @"NoCancelledDependencies";
35 | }
36 |
37 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation {
38 | return nil;
39 | }
40 |
41 | - (void)evaluateConditionForOperation:(OPOperation *)operation
42 | completion:(void (^)(OPOperationConditionResultStatus result, NSError *error))completion
43 | {
44 | // Verify that all of the dependencies executed.
45 | NSArray *cancelled = [operation.dependencies filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"cancelled = YES"]];
46 |
47 | // Satisfied until not
48 | OPOperationConditionResultStatus resultStatus = OPOperationConditionResultStatusSatisfied;
49 |
50 | NSError *error;
51 |
52 | if(cancelled.count != 0) {
53 | // At least one dependency was cancelled; the condition was not satisfied.
54 | NSDictionary *userInfo = @{
55 | kOPOperationConditionKey: NSStringFromClass([self class]),
56 | kOPCancelledDependenciesKey: cancelled
57 | };
58 |
59 | error = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:userInfo];
60 | resultStatus = OPOperationConditionResultStatusFailed;
61 | }
62 |
63 | completion(resultStatus, error);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operation Queue/OPOperationQueue.h:
--------------------------------------------------------------------------------
1 | // OPOperationQueue.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 |
25 | @class OPOperationQueue;
26 |
27 |
28 | /**
29 | * The delegate of an `OPOperationQueue` can respond to `OPOperation` lifecycle
30 | * events by implementing these methods.
31 | *
32 | * In general, implementing `OPOperationQueueDelegate` is not necessary;
33 | * you would want to use an `OPOperationObserver` instead.
34 | * However, there are a couple of situations where using
35 | * `OPOperationQueueDelegate` can lead to simpler code.
36 | * For example, `OPGroupOperation` is the delegate of its own internal
37 | * `OPOperationQueue` and uses it to manage dependencies.
38 | */
39 | @protocol OPOperationQueueDelegate
40 |
41 | @optional
42 |
43 | - (void)operationQueue:(OPOperationQueue *)operationQueue willAddOperation:(NSOperation *)operation;
44 |
45 | - (void)operationQueue:(OPOperationQueue *)operationQueue operationDidFinish:(NSOperation *)operation withErrors:(NSArray *)errors;
46 |
47 | @end
48 |
49 |
50 | /**
51 | * `OPOperationQueue` is an `NSOperationQueue` subclass that implements a large
52 | * number of "extra features" related to the `OPOperation` class:
53 | *
54 | * - Notifying a delegate of all operation completion
55 | * - Extracting generated dependencies from operation conditions
56 | * - Setting up dependencies to enforce mutual exclusivity
57 | */
58 | @interface OPOperationQueue : NSOperationQueue
59 |
60 | @property (weak, nonatomic) id delegate;
61 |
62 | - (void)addOperation:(NSOperation *)operation;
63 |
64 | - (void)addOperations:(NSArray *)operations waitUntilFinished:(BOOL)wait;
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Networking/OPURLSessionTaskOperation.h:
--------------------------------------------------------------------------------
1 | // OPURLSessionOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 |
25 | /**
26 | * `OPURLSessionTaskOperation` is an `OPOperation` that lifts an `NSURLSessionTask`
27 | * into an operation.
28 | *
29 | * Note that this operation does not participate in any of the delegate callbacks
30 | * of an `NSURLSession`, but instead uses Key-Value-Observing to know when the
31 | * task has been completed. By default the operation gets notified of errors that occur during
32 | * execution of the task. Upon completion, if the task has produced an error,
33 | * `-finishWithError:` will receive this error and the operation will accrue the error
34 | * from the task as an internal error.
35 | *
36 | * As an option, one can set the value of `shouldSuppressErrors` to YES
37 | * and the operation will not get notified about any errors that occurred during
38 | * execution of the task.
39 | *
40 | * @see shouldSuppressErrors
41 | *
42 | * - returns: An instance of an `OPURLSessionTaskOperation`
43 | */
44 | @interface OPURLSessionTaskOperation : OPOperation
45 |
46 | - (instancetype)initWithTask:(NSURLSessionTask *)task NS_DESIGNATED_INITIALIZER;
47 |
48 | /**
49 | * Evaluated upon completion of the provided `NSURLSessionTask`, this value
50 | * dictates how errors occurring during the execution of the task are handled.
51 | *
52 | * If set to YES, completion of the task will not pass along any errors that
53 | * may have occurred during execution to the operation via -finishedWithError:.
54 | *
55 | * Defaults to NO
56 | */
57 | @property (assign, nonatomic) BOOL shouldSuppressErrors;
58 |
59 | /**
60 | * Unused `-init` method.
61 | * @see -initWithTask:
62 | */
63 | - (instancetype)init NS_UNAVAILABLE;
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Misc/OPBlockOperation.h:
--------------------------------------------------------------------------------
1 | // OPBlockOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 |
25 | /**
26 | * An operation block that takes a block as it's parameter
27 | *
28 | * @param ^completion: Block to be executed upon completion of an
29 | * `OPBlockOperation`
30 | */
31 | typedef void (^OPOperationBlock)(void (^completion)(void));
32 |
33 |
34 | /**
35 | * A subclass of `OPOperation` to execute a block.
36 | * - returns: An instance of an `OPBlockOperation`
37 | */
38 | @interface OPBlockOperation : OPOperation
39 |
40 | /**
41 | * Designated Initialized for `OPBlockOperation`
42 | *
43 | * @param block: The block to run when the operation executes. This
44 | * block will be run on an arbitrary queue. The parameter passed to the
45 | * block **MUST** be invoked by your code, or else the `OPBlockOperation`
46 | * will never finish executing. If this parameter is `nil`, the operation
47 | * will immediately finish.
48 | *
49 | * @return An instance of an `OPBlockOperation`
50 | */
51 | - (instancetype)initWithBlock:(OPOperationBlock)block NS_DESIGNATED_INITIALIZER;
52 |
53 | /**
54 | * A convenience initializer to execute a block on the main queue.
55 | *
56 | * @param mainQueueBlock: The block to execute on the main queue. Note
57 | * that this block does not have a "continuation" block to execute (unlike
58 | * the designated initializer). The operation will be automatically ended
59 | * after the `mainQueueBlock` is executed.
60 | *
61 | * @return An instance of an `OPBlockOperation` that will run on the main queue
62 | */
63 | - (instancetype)initWithMainQueueBlock:(void (^)(void))mainQueueBlock;
64 |
65 | /**
66 | * Unused `-init` method.
67 | * @see -initWithBlock:
68 | * @see -initWithMainQueueBlock:
69 | */
70 | - (instancetype)init NS_UNAVAILABLE;
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPOperationConditionMutuallyExclusive.m:
--------------------------------------------------------------------------------
1 | // OPOperationConditionMutuallyExclusive.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationConditionMutuallyExclusive.h"
23 |
24 |
25 | @interface OPOperationConditionMutuallyExclusive ()
26 |
27 | @property (copy, nonatomic) Class cls;
28 |
29 | @end
30 |
31 | @implementation OPOperationConditionMutuallyExclusive
32 |
33 | - (NSString *)debugDescription {
34 | return [NSString stringWithFormat:@"%@ %@", [super debugDescription], [self name]];
35 | }
36 |
37 | #pragma mark - OPOperationCondition Protocol
38 | #pragma mark -
39 |
40 | - (NSString *)name
41 | {
42 | return [NSString stringWithFormat:@"MutuallyExclusive<%@>", NSStringFromClass(self.cls)];
43 | }
44 |
45 | - (BOOL)isMutuallyExclusive
46 | {
47 | return YES;
48 | }
49 |
50 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
51 | {
52 | return nil;
53 | }
54 |
55 | - (void)evaluateConditionForOperation:(OPOperation *)operation
56 | completion:(void (^)(OPOperationConditionResultStatus result, NSError *error))completion
57 | {
58 | completion(OPOperationConditionResultStatusSatisfied, nil);
59 | }
60 |
61 |
62 | #pragma mark - Lifecycle
63 | #pragma mark -
64 |
65 | + (OPOperationConditionMutuallyExclusive *)alertPresentationExclusivity
66 | {
67 | return [OPOperationConditionMutuallyExclusive mutuallyExclusiveWith:[OPAlertPresentation class]];
68 | }
69 |
70 | + (OPOperationConditionMutuallyExclusive *)mutuallyExclusiveWith:(Class)cls
71 | {
72 | return [[OPOperationConditionMutuallyExclusive alloc] initWithClass:cls];
73 | }
74 |
75 | - (instancetype)initWithClass:(Class)cls
76 | {
77 | self = [super init];
78 | if (!self) {
79 | return nil;
80 | }
81 |
82 | _cls = [cls copy];
83 |
84 | return self;
85 | }
86 |
87 | @end
88 |
89 |
90 | #pragma mark - OPAlertPresentation
91 |
92 | @implementation OPAlertPresentation
93 | @end
94 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Observers/OPBlockObserver.m:
--------------------------------------------------------------------------------
1 | // OPBlockObserver.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPBlockObserver.h"
23 |
24 |
25 | @interface OPBlockObserver ()
26 |
27 | - (instancetype)init NS_DESIGNATED_INITIALIZER;
28 |
29 | @end
30 |
31 |
32 | @implementation OPBlockObserver
33 |
34 |
35 | #pragma mark - OPOperationObserver Protocol
36 | #pragma mark -
37 |
38 | - (void)operationDidStart:(OPOperation *)operation
39 | {
40 | if ([self startHandler]) {
41 | self.startHandler(operation);
42 | }
43 | }
44 |
45 | - (void)operation:(OPOperation *)operation didProduceOperation:(NSOperation *)newOperation
46 | {
47 | if ([self produceHander]) {
48 | self.produceHander(operation, newOperation);
49 | }
50 | }
51 |
52 | - (void)operation:(OPOperation *)operation didFinishWithErrors:(NSArray *)errors
53 | {
54 | if ([self finishHandler]) {
55 | self.finishHandler(operation, errors);
56 | }
57 | }
58 |
59 |
60 | #pragma mark - Lifecycle
61 | #pragma mark -
62 |
63 | - (instancetype)initWithStartHandler:(void (^)(OPOperation *operation))startHandler
64 | produceHandler:(void (^)(OPOperation *operation, NSOperation *newOperation))produceHandler
65 | finishHandler:(void (^)(OPOperation *operation, NSArray *errors))finishHandler;
66 | {
67 | self = [super init];
68 | if (!self) {
69 | return nil;
70 | }
71 |
72 | _startHandler = [startHandler copy];
73 | _produceHander = [produceHandler copy];
74 | _finishHandler = [finishHandler copy];
75 |
76 | return self;
77 | }
78 |
79 | - (instancetype)initWithFinishHandler:(void (^)(OPOperation *operation, NSArray *errors))finishHandler
80 | {
81 | return [self initWithStartHandler:nil produceHandler:nil finishHandler:finishHandler];
82 | }
83 |
84 | - (instancetype)init
85 | {
86 | self = [super init];
87 | if (!self) {
88 | return nil;
89 | }
90 |
91 | return self;
92 | }
93 |
94 | @end
95 |
--------------------------------------------------------------------------------
/Example/Operative/OPAppDelegate.m:
--------------------------------------------------------------------------------
1 | // OPAppDelegate.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPAppDelegate.h"
23 |
24 | @implementation OPAppDelegate
25 |
26 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
27 | {
28 | // Override point for customization after application launch.
29 | return YES;
30 | }
31 |
32 | - (void)applicationWillResignActive:(UIApplication *)application
33 | {
34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
36 | }
37 |
38 | - (void)applicationDidEnterBackground:(UIApplication *)application
39 | {
40 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
41 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
42 | }
43 |
44 | - (void)applicationWillEnterForeground:(UIApplication *)application
45 | {
46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
47 | }
48 |
49 | - (void)applicationDidBecomeActive:(UIApplication *)application
50 | {
51 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
52 | }
53 |
54 | - (void)applicationWillTerminate:(UIApplication *)application
55 | {
56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPOperationConditionEvaluator.m:
--------------------------------------------------------------------------------
1 | // OPOperationConditionEvaluator.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperationConditionEvaluator.h"
23 | #import "OPOperationCondition.h"
24 | #import "NSError+Operative.h"
25 |
26 |
27 | @implementation OPOperationConditionEvaluator
28 |
29 | + (void)evaluateConditions:(NSArray *)conditions
30 | operation:(OPOperation *)operation
31 | completion:(void (^)(NSArray *failures))completion;
32 | {
33 | // Check conditions.
34 | dispatch_group_t conditionGroup = dispatch_group_create();
35 |
36 | NSMutableArray *results = [[NSMutableArray alloc] init];
37 | [conditions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
38 | [results addObject:[NSNull null]];
39 | }];
40 |
41 | // Ask each condition to evaluate and store its result in the "results" array.
42 | [conditions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
43 | id condition = obj;
44 |
45 | dispatch_group_enter(conditionGroup);
46 | [condition evaluateConditionForOperation:operation completion:^(OPOperationConditionResultStatus result, NSError *error) {
47 | if (error) {
48 | results[idx] = error;
49 | }
50 | dispatch_group_leave(conditionGroup);
51 | }];
52 | }];
53 |
54 | // After all the conditions have evaluated, this block will execute
55 | dispatch_group_notify(conditionGroup, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
56 | // Aggregate the errors that occurred, in order.
57 | NSMutableArray *failures = [[NSMutableArray alloc] init];
58 | [results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
59 | if ([obj isKindOfClass:[NSError class]]) {
60 | [failures addObject:obj];
61 | }
62 | }];
63 |
64 | // If any of the conditions caused this operation to be cancelled, check for that
65 | if ([operation isCancelled]) {
66 | [failures addObject:[NSError errorWithCode:OPOperationErrorCodeConditionFailed]];
67 | }
68 |
69 | completion(failures);
70 | });
71 | }
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Categories/UIUserNotificationSettings+Operative.m:
--------------------------------------------------------------------------------
1 | // UIUserNotificationSettings+Operative.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #if TARGET_OS_IPHONE
23 |
24 | #import "UIUserNotificationSettings+Operative.h"
25 | #import "NSMutableDictionary+Operative.h"
26 |
27 | @implementation UIUserNotificationSettings (Operative)
28 |
29 | - (BOOL)containsSettings:(UIUserNotificationSettings *)settings;
30 | {
31 | if (((self.types & UIUserNotificationTypeBadge) == 0) &&
32 | ((settings.types & UIUserNotificationTypeBadge) != 0)) {
33 | return NO;
34 | } else if (((self.types & UIUserNotificationTypeSound) == 0) &&
35 | ((settings.types & UIUserNotificationTypeSound) != 0)) {
36 | return NO;
37 | } else if (((self.types & UIUserNotificationTypeAlert) == 0) &&
38 | ((settings.types & UIUserNotificationTypeAlert) != 0)) {
39 | return NO;
40 | }
41 |
42 | NSSet *otherCategories = settings.categories ? settings.categories : [NSSet set];
43 | NSSet *myCategories = self.categories ? self.categories : [NSSet set];
44 |
45 | return [otherCategories isSubsetOfSet:myCategories];
46 | }
47 |
48 | - (UIUserNotificationSettings *)settingsByMerging:(UIUserNotificationSettings *)settings;
49 | {
50 | UIUserNotificationType mergedTypes = settings.types & self.types;
51 |
52 | NSSet *myCategories = self.categories ? self.categories : [NSSet set];
53 |
54 | NSMutableDictionary *existingCategoriesByIdentifier = [NSMutableDictionary sequence:myCategories keyMapper:^id(id obj) {
55 | UIUserNotificationCategory *type = obj;
56 | return type.identifier;
57 | }];
58 |
59 | NSSet *newCategories = settings.categories ? settings.categories : [NSSet set];
60 | NSMutableDictionary *newCategoriesByIdentifier = [NSMutableDictionary sequence:newCategories keyMapper:^id(id obj) {
61 | UIUserNotificationCategory *type = obj;
62 | return type.identifier;
63 | }];
64 |
65 | [newCategoriesByIdentifier enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
66 | existingCategoriesByIdentifier[key] = obj;
67 | }];
68 |
69 | NSSet *mergedCategories = [NSSet setWithArray:existingCategoriesByIdentifier.allValues];
70 | return [UIUserNotificationSettings settingsForTypes:mergedTypes categories:mergedCategories];
71 | }
72 |
73 | @end
74 |
75 | #endif
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPOperationCondition.h:
--------------------------------------------------------------------------------
1 | // OPOperationCondition.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 | /**
25 | * An enum to indicate whether an `OPOperationCondition` was satisfied,
26 | * or if it failed with an error.
27 | */
28 | typedef NS_ENUM(NSUInteger, OPOperationConditionResultStatus){
29 | // Operation condition was satisfied
30 | OPOperationConditionResultStatusSatisfied,
31 | // Operation condition failed
32 | OPOperationConditionResultStatusFailed,
33 | };
34 |
35 |
36 | /**
37 | * A protocol for defining conditions that must be satisfied in order for an
38 | * operation to begin execution.
39 | */
40 | @protocol OPOperationCondition
41 |
42 | /**
43 | * The name of the condition. This is used in userInfo dictionaries of
44 | * `OPOperationConditionResultStatusFailed` errors as the value of the
45 | * `OPOperationConditionKey` key.
46 | */
47 | @property (strong, nonatomic, readonly) NSString *name;
48 |
49 | /**
50 | * Specifies whether multiple instances of the conditionalized operation may
51 | * be executing simultaneously.
52 | */
53 | @property (assign, nonatomic, readonly) BOOL isMutuallyExclusive;
54 |
55 | /**
56 | * Some conditions may have the ability to satisfy the condition if another
57 | * operation is executed first. Use this method to return an operation that
58 | * (for example) asks for permission to perform the operation.
59 | *
60 | * @param operation: The `OPOperation` to which the Condition has been added.
61 | *
62 | * @return An `NSOperation`, if a dependency should be automatically added.
63 | * Otherwise, `nil`.
64 | *
65 | * @note Only a single operation may be returned as a dependency. If you
66 | * find that you need to return multiple operations, then you should be
67 | * expressing that as multiple conditions. Alternatively, you could return
68 | * a single `OPGroupOperation` that executes multiple operations internally.
69 | */
70 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation;
71 |
72 | /**
73 | * Evaluate the condition, to see if it has been satisfied or not.
74 | *
75 | * TODO:// Get these params doc'd correctly
76 | * @param operation -
77 | * @param completion -
78 | */
79 | - (void)evaluateConditionForOperation:(OPOperation *)operation
80 | completion:(void (^)(OPOperationConditionResultStatus result, NSError *error))completion;
81 |
82 | @end
83 |
84 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Misc/OPGroupOperation.h:
--------------------------------------------------------------------------------
1 | // OPGroupOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPOperation.h"
23 |
24 |
25 | /**
26 | * A subclass of `OPOperation` that executes zero or more operations as part
27 | * of its own execution. This class of operation is very useful for abstracting
28 | * several smaller operations into a larger operation.
29 | *
30 | * Additionally, `OPGroupOperation`s are useful if you establish a chain of
31 | * dependencies, but part of the chain may "loop". For example, if you have an
32 | * operation that requires the user to be authenticated, you may consider
33 | * putting the "login" operation inside a group operation. That way,
34 | * the "login" operation may produce subsequent operations
35 | * (still within the outer `OPGroupOperation`) that will all be executed before
36 | * the rest of the operations in the initial chain of operations.
37 | *
38 | * - returns: An instance of `OPGroupOperation
39 | */
40 | @interface OPGroupOperation : OPOperation
41 |
42 | /**
43 | * Initializes an `OPGroupOperation` object and adds the provided operations to
44 | * its internal queue
45 | *
46 | * @param operations An `NSArray` of operations to be group together into a
47 | * single executable operation.
48 | *
49 | * @return An `OPGroupOperation` object
50 | */
51 | - (instancetype)initWithOperations:(NSArray *)operations NS_DESIGNATED_INITIALIZER;
52 |
53 | /**
54 | * Adds an operation to the group after instantiation
55 | *
56 | * @param operation Operation to add to the group
57 | */
58 | - (void)addOperation:(NSOperation *)operation;
59 |
60 | /**
61 | * Add multiple operations to the group after instantiation
62 | *
63 | * @param operations Array of operations to add to the group
64 | */
65 | - (void)addOperations:(NSArray *)operations;
66 |
67 | /**
68 | * Note that some part of execution has produced an error.
69 | * Errors aggregated through this method will be included in the final array
70 | * of errors reported to observers and to the `-finished:` method.
71 | *
72 | * @param error `NSError` to be aggregated
73 | */
74 | - (void)aggregateError:(NSError *)error;
75 |
76 | /**
77 | * Method called upon finish of an operation within the group
78 | * To be overriden by subclass of `OPGroupOperation`.
79 | *
80 | * @param operation Operation that did finish.
81 | * @param errors Array of `NSErrors` during execution of operation or nil.
82 | */
83 | - (void)operationDidFinish:(NSOperation *)operation withErrors:(NSArray *)errors;
84 |
85 | @end
86 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPPhotosCondition.m:
--------------------------------------------------------------------------------
1 | // OPPhotosCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | @import Photos;
23 |
24 | #import "OPPhotosCondition.h"
25 | #import "OPOperationConditionMutuallyExclusive.h"
26 |
27 | #import "NSError+Operative.h"
28 |
29 |
30 | /**
31 | * A private `OPOperation` that will request access to the user's Photos, if it
32 | * has not already been granted.
33 | */
34 | @interface OPPhotosPermissionOperation : OPOperation
35 |
36 | @end
37 |
38 |
39 | @implementation OPPhotosCondition
40 |
41 |
42 | #pragma mark - OPOperationCondition Protocol
43 | #pragma mark -
44 |
45 | - (NSString *)name
46 | {
47 | return @"Photos";
48 | }
49 |
50 | - (BOOL)isMutuallyExclusive
51 | {
52 | return NO;
53 | }
54 |
55 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
56 | {
57 | return [[OPPhotosPermissionOperation alloc] init];
58 | }
59 |
60 | - (void)evaluateConditionForOperation:(OPOperation *)operation
61 | completion:(void (^)(OPOperationConditionResultStatus, NSError *))completion
62 | {
63 | PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
64 |
65 | if (status == PHAuthorizationStatusAuthorized) {
66 | completion(OPOperationConditionResultStatusSatisfied, nil);
67 | } else {
68 | NSDictionary *userInfo = @{ kOPOperationConditionKey : [self name] };
69 | NSError *error = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:userInfo];
70 | completion(OPOperationConditionResultStatusFailed, error);
71 | }
72 | }
73 |
74 | @end
75 |
76 |
77 | @implementation OPPhotosPermissionOperation
78 |
79 |
80 | #pragma mark - Lifecycle
81 | #pragma mark -
82 |
83 | - (instancetype)init
84 | {
85 | self = [super init];
86 | if (!self) {
87 | return nil;
88 | }
89 |
90 | [self addCondition:[OPOperationConditionMutuallyExclusive alertPresentationExclusivity]];
91 |
92 | return self;
93 | }
94 |
95 |
96 | #pragma mark - Overrides
97 | #pragma mark -
98 |
99 | - (void)execute
100 | {
101 | PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
102 | if (status == PHAuthorizationStatusNotDetermined) {
103 | dispatch_async(dispatch_get_main_queue(), ^{
104 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
105 | [self finish];
106 | }];
107 | });
108 | } else {
109 | [self finish];
110 | }
111 | }
112 |
113 | @end
114 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Networking/OPURLSessionTaskOperation.m:
--------------------------------------------------------------------------------
1 | // OPURLSessionOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of oftware.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPURLSessionTaskOperation.h"
23 |
24 |
25 | static void * OPURLSessionOperationKVOContext = &OPURLSessionOperationKVOContext;
26 |
27 |
28 | @interface OPURLSessionTaskOperation ()
29 |
30 | @property (strong, nonatomic) NSURLSessionTask *task;
31 |
32 | @end
33 |
34 |
35 | @implementation OPURLSessionTaskOperation
36 |
37 |
38 | #pragma mark - Overrides
39 | #pragma mark -
40 |
41 | - (void)execute
42 | {
43 | NSAssert([self.task state] == NSURLSessionTaskStateSuspended, @"Task was resumed by something other than %@", self);
44 |
45 | [self.task addObserver:self
46 | forKeyPath:NSStringFromSelector(@selector(state))
47 | options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew)
48 | context:OPURLSessionOperationKVOContext];
49 |
50 | [self.task resume];
51 | }
52 |
53 | - (void)cancel
54 | {
55 | [self.task cancel];
56 | [super cancel];
57 | }
58 |
59 |
60 | #pragma mark - KVO
61 | #pragma mark -
62 |
63 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
64 | {
65 | if (context == OPURLSessionOperationKVOContext) {
66 | if (object == [self task] && [keyPath isEqualToString:NSStringFromSelector(@selector(state))]) {
67 | if ([object state] == NSURLSessionTaskStateCompleted) {
68 | @try {
69 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state)) context:context];
70 | }
71 | @catch (NSException *__unused exception) {}
72 |
73 | if ([self shouldSuppressErrors]) {
74 | [self finish];
75 | } else {
76 | [self finishWithError:[self.task error]];
77 | }
78 | }
79 | }
80 | } else {
81 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
82 | }
83 | }
84 |
85 |
86 | #pragma mark - Lifecycle
87 | #pragma mark -
88 |
89 | - (instancetype)initWithTask:(NSURLSessionTask *)task
90 | {
91 | self = [super init];
92 | if (!self) {
93 | return nil;
94 | }
95 |
96 | NSAssert([task state] == NSURLSessionTaskStateSuspended, @"Tasks must be suspended.");
97 |
98 | _task = task;
99 | _shouldSuppressErrors = NO;
100 |
101 | return self;
102 | }
103 |
104 | @end
105 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPNegatedCondition.m:
--------------------------------------------------------------------------------
1 | // OPNegatedCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPNegatedCondition.h"
23 | #import "NSError+Operative.h"
24 |
25 |
26 | @interface OPNegatedCondition ()
27 |
28 | /**
29 | * Underlying condition which is evaluated.
30 | */
31 | @property (strong, nonatomic, readonly) id condition;
32 |
33 | @end
34 |
35 |
36 | @implementation OPNegatedCondition
37 |
38 |
39 | #pragma mark - Lifecycle
40 | #pragma mark -
41 |
42 | - (instancetype)initWithCondition:(id )condition
43 | {
44 | self = [super init];
45 |
46 | _condition = condition;
47 |
48 | return self;
49 | }
50 |
51 |
52 | #pragma mark - OPOperationCondition Protocol
53 | #pragma mark -
54 |
55 | - (NSString *)name
56 | {
57 | return [NSString stringWithFormat:@"Not<%@>", [self.condition name]];
58 | }
59 |
60 | - (BOOL)isMutuallyExclusive
61 | {
62 | return [self.condition isMutuallyExclusive];
63 | }
64 |
65 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
66 | {
67 | return [self.condition dependencyForOperation:operation];
68 | }
69 |
70 | - (void)evaluateConditionForOperation:(OPOperation *)operation
71 | completion:(void (^)(__unused OPOperationConditionResultStatus aResult, __unused NSError *anError))completion
72 | {
73 | void (^underlyingCompletion)(OPOperationConditionResultStatus, NSError *) = ^(OPOperationConditionResultStatus result, __unused NSError *error) {
74 | switch (result) {
75 | case OPOperationConditionResultStatusSatisfied: {
76 | // If the composed condition succeeded, then this one failed.
77 | NSDictionary *userInfo = @{
78 | kOPOperationConditionKey : NSStringFromClass([self class]),
79 | kOPOperationNegatedConditionKey : NSStringFromClass([self.condition class])
80 | };
81 | NSError *negatedError = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:userInfo];
82 | completion(OPOperationConditionResultStatusFailed, negatedError);
83 | }
84 | break;
85 |
86 | case OPOperationConditionResultStatusFailed: {
87 | // If the composed condition failed, then this one succeeded.
88 | completion(OPOperationConditionResultStatusSatisfied, nil);
89 | }
90 | break;
91 |
92 | default:
93 | break;
94 | }
95 | };
96 |
97 | [self.condition evaluateConditionForOperation:operation
98 | completion:underlyingCompletion];
99 | }
100 |
101 |
102 | @end
--------------------------------------------------------------------------------
/Example/Tests/BlockObserversTests.m:
--------------------------------------------------------------------------------
1 | // BlockObserversTests.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 | #import
25 |
26 | @interface BlockObserversTests : XCTestCase
27 |
28 | @end
29 |
30 | @implementation BlockObserversTests
31 |
32 | - (void)setUp {
33 | [super setUp];
34 | // Put setup code here. This method is called before the invocation of each test method in the class.
35 | }
36 |
37 | - (void)tearDown {
38 | // Put teardown code here. This method is called after the invocation of each test method in the class.
39 | [super tearDown];
40 | }
41 |
42 | - (void)testStartHandler {
43 | XCTestExpectation *expectation = [self expectationWithDescription:@"Block observer should call start handler"];
44 |
45 | OPOperationQueue *operationQueue = [[OPOperationQueue alloc] init];
46 | OPOperation *operation = [[OPOperation alloc] init];
47 |
48 | [operation addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
49 | [expectation fulfill];
50 | } produceHandler:^(OPOperation *operation, NSOperation *newOperation) {
51 |
52 | } finishHandler:^(OPOperation *operation, NSArray *errors) {
53 |
54 | }]];
55 |
56 | [operationQueue addOperation:operation];
57 |
58 | [self waitForExpectationsWithTimeout:1 handler:nil];
59 | }
60 |
61 | - (void)testFinishHandler {
62 | XCTestExpectation *expectation = [self expectationWithDescription:@"Block observer should call finish handler"];
63 |
64 | OPOperationQueue *operationQueue = [[OPOperationQueue alloc] init];
65 | OPOperation *operation = [[OPOperation alloc] init];
66 |
67 | [operation addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
68 |
69 | } produceHandler:^(OPOperation *operation, NSOperation *newOperation) {
70 |
71 | } finishHandler:^(OPOperation *operation, NSArray *errors) {
72 | [expectation fulfill];
73 | }]];
74 |
75 | [operationQueue addOperation:operation];
76 |
77 | [self waitForExpectationsWithTimeout:1 handler:nil];
78 | }
79 |
80 | - (void)testProduceHandler {
81 | XCTestExpectation *expectation = [self expectationWithDescription:@"Block observer should call produce handler"];
82 |
83 | OPOperationQueue *operationQueue = [[OPOperationQueue alloc] init];
84 | OPOperation *operation = [[OPOperation alloc] init];
85 |
86 | [operation addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
87 |
88 | } produceHandler:^(OPOperation *operation, NSOperation *newOperation) {
89 | [expectation fulfill];
90 | } finishHandler:^(OPOperation *operation, NSArray *errors) {
91 | [operation produceOperation:[[OPOperation alloc] init]];
92 | }]];
93 |
94 | [operationQueue addOperation:operation];
95 |
96 | [self waitForExpectationsWithTimeout:1 handler:nil];
97 | }
98 |
99 | @end
100 |
--------------------------------------------------------------------------------
/Example/Operative.xcodeproj/xcshareddata/xcschemes/Operative-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Operations/Misc/OPLocationOperation.m:
--------------------------------------------------------------------------------
1 | // OPLocationOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | #import "OPLocationOperation.h"
24 |
25 | #import "OPOperationConditionMutuallyExclusive.h"
26 | #import "OPLocationCondition.h"
27 |
28 | @interface OPLocationOperation ()
29 |
30 | @property (assign, nonatomic) CLLocationAccuracy accuracy;
31 |
32 | @property (strong, nonatomic) CLLocationManager *manager;
33 |
34 | @property (copy, nonatomic) void (^handler)(CLLocation *);
35 |
36 | - (instancetype)init NS_DESIGNATED_INITIALIZER;
37 |
38 | @end
39 |
40 |
41 | @implementation OPLocationOperation
42 |
43 |
44 | #pragma mark - Overrides
45 | #pragma mark -
46 |
47 | - (void)execute
48 | {
49 | dispatch_async(dispatch_get_main_queue(), ^{
50 | /**
51 | * `CLLocationManager` needs to be created on a thread with an active
52 | * run loop, so for simplicity we do this on the main queue.
53 | */
54 | CLLocationManager *manager = [[CLLocationManager alloc] init];
55 | [manager setDesiredAccuracy:[self accuracy]];
56 | [manager setDelegate:self];
57 | [manager startUpdatingLocation];
58 |
59 | [self setManager:manager];
60 | });
61 | }
62 |
63 | - (void)cancel
64 | {
65 | dispatch_async(dispatch_get_main_queue(), ^{
66 | [self stopLocationUpdates];
67 | [super cancel];
68 | });
69 | }
70 |
71 | - (void)stopLocationUpdates
72 | {
73 | [self.manager stopUpdatingLocation];
74 | [self setManager:nil];
75 | }
76 |
77 |
78 | #pragma mark - CLLocationManagerDelegate
79 | #pragma mark -
80 |
81 | - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
82 | {
83 | [locations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
84 | CLLocation *location = obj;
85 | if (location.horizontalAccuracy < [self accuracy]) {
86 | [self stopLocationUpdates];
87 | self.handler(location);
88 | [self finish];
89 |
90 | *stop = YES;
91 | }
92 | }];
93 | }
94 |
95 | - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
96 | {
97 | [self stopLocationUpdates];
98 | [self finishWithError:error];
99 | }
100 |
101 |
102 | #pragma mark - Lifecycle
103 | #pragma mark -
104 |
105 | - (instancetype)initWithAccuracy:(CLLocationAccuracy)accuracy
106 | locationHandler:(void (^)(CLLocation *location))locationHandler
107 | {
108 | self = [super init];
109 | if (!self) {
110 | return nil;
111 | }
112 |
113 | _accuracy = accuracy;
114 | _handler = [locationHandler copy];
115 |
116 | [self addCondition:[[OPLocationCondition alloc] initWithUsage:OPLocationConditionWhenInUse]];
117 | [self addCondition:[[OPOperationConditionMutuallyExclusive alloc] initWithClass:[CLLocationManager class]]];
118 |
119 | return self;
120 | }
121 |
122 | - (instancetype)init
123 | {
124 | self = [super init];
125 | if (!self) {
126 | return nil;
127 | }
128 |
129 | return self;
130 | }
131 |
132 | @end
133 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Observers/OPTimeoutObserver.m:
--------------------------------------------------------------------------------
1 | // OPTimeoutObserver.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPTimeoutObserver.h"
23 | #import "OPOperation.h"
24 | #import "NSError+Operative.h"
25 |
26 |
27 | static NSString *const kOPTimeoutObserverErrorKey = @"OPTimeoutObserverError";
28 |
29 |
30 | @interface OPTimeoutObserver ()
31 |
32 | @property (assign, nonatomic) NSTimeInterval timeout;
33 |
34 | #if OS_OBJECT_USE_OBJC
35 | @property (strong, nonatomic) dispatch_source_t timer;
36 | #else
37 | @property (assign, nonatomic) dispatch_source_t timer;
38 | #endif
39 |
40 | @end
41 |
42 |
43 | @implementation OPTimeoutObserver
44 |
45 | #pragma mark - OPOperationObserver Protocol
46 | #pragma mark -
47 |
48 | - (void)operationDidStart:(OPOperation *)operation
49 | {
50 | // set up timeout handler
51 | void(^timeoutHandler)() = ^{
52 | /**
53 | * Cancel the operation if it hasn't finished and hasn't already
54 | * been cancelled.
55 | */
56 | if (![operation isFinished] && ![operation isCancelled]) {
57 | NSDictionary *userInfo = @{ kOPTimeoutObserverErrorKey : @(([self timeout])) };
58 | NSError *error = [NSError errorWithCode:OPOperationErrorCodeExecutionFailed userInfo:userInfo];
59 | [operation cancelWithError:error];
60 | }
61 | };
62 |
63 | // When the operation starts, queue up a block to cause it to time out.
64 | self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0));
65 |
66 | // Cancel operation immediately if timer wasn't created
67 | if(!self.timer) {
68 | timeoutHandler();
69 | return;
70 | }
71 |
72 | // calculate time delta
73 | int64_t delta = (int64_t)(self.timeout * NSEC_PER_SEC);
74 |
75 | // calculate the leeway for timer using the same way as dispatch_after
76 | int64_t leeway = delta / 10;
77 | if(leeway < NSEC_PER_MSEC) leeway = NSEC_PER_MSEC;
78 | if(leeway > 60 * NSEC_PER_SEC) leeway = 60 * NSEC_PER_SEC;
79 |
80 | dispatch_time_t when = dispatch_walltime(NULL, delta);
81 | dispatch_source_set_event_handler(self.timer, timeoutHandler);
82 | dispatch_source_set_timer(self.timer, when, DISPATCH_TIME_FOREVER, leeway);
83 | dispatch_resume(self.timer);
84 | }
85 |
86 | - (void)operation:(OPOperation *)operation didProduceOperation:(NSOperation *)newOperation
87 | {
88 | // No-op
89 | }
90 |
91 | - (void)operation:(OPOperation *)operation didFinishWithErrors:(NSArray *)errors
92 | {
93 | if(!self.timer) {
94 | return;
95 | }
96 |
97 | // Cancel and release the timer
98 | dispatch_source_cancel(self.timer);
99 |
100 | #if !OS_OBJECT_USE_OBJC
101 | dispatch_release(self.timer);
102 | #endif
103 |
104 | self.timer = nil;
105 | }
106 |
107 |
108 | #pragma mark - Lifecycle
109 | #pragma mark -
110 |
111 | - (instancetype)initWithTimeout:(NSTimeInterval)timeout;
112 | {
113 | self = [super init];
114 | if (!self) {
115 | return nil;
116 | }
117 |
118 | _timeout = timeout;
119 |
120 | return self;
121 | }
122 |
123 | @end
124 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operation Queue/OPExclusivityController.m:
--------------------------------------------------------------------------------
1 | // OPExclusivityController.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPExclusivityController.h"
23 |
24 | @interface OPExclusivityController()
25 |
26 | @property (strong, nonatomic) NSMutableDictionary *operations;
27 |
28 | #if OS_OBJECT_USE_OBJC
29 | @property (strong, nonatomic) dispatch_queue_t serialQueue;
30 | #else
31 | @property (assign, nonatomic) dispatch_queue_t serialQueue;
32 | #endif
33 |
34 | @end
35 |
36 | @implementation OPExclusivityController
37 |
38 |
39 | #pragma mark - Add & Remove Operations
40 | #pragma mark -
41 |
42 | - (void)addOperation:(OPOperation *)operation categories:(NSArray *)categories
43 | {
44 | dispatch_sync([self serialQueue], ^{
45 | for (NSString *category in categories) {
46 | [self noqueue_addOperation:operation category:category];
47 | }
48 | });
49 | }
50 |
51 |
52 | - (void)removeOperation:(OPOperation *)operation categories:(NSArray *)categories
53 | {
54 | dispatch_sync([self serialQueue], ^{
55 | for (NSString *category in categories) {
56 | [self noqueue_removeOperation:operation category:category];
57 | }
58 | });
59 | }
60 |
61 |
62 | #pragma mark - Operation Management
63 | #pragma mark -
64 |
65 | - (void)noqueue_addOperation:(OPOperation *)operation category:(NSString *)category
66 | {
67 | NSArray *operationsWithThisCategory = self.operations[category] ?: @[];
68 |
69 | if ([operationsWithThisCategory count]) {
70 | OPOperation *op = [operationsWithThisCategory lastObject];
71 | [operation addDependency:op];
72 | }
73 |
74 | operationsWithThisCategory = [operationsWithThisCategory arrayByAddingObject:operation];
75 |
76 | self.operations[category] = operationsWithThisCategory;
77 | }
78 |
79 | - (void)noqueue_removeOperation:(OPOperation *)operation category:(NSString *)category
80 | {
81 | if (!self.operations[category]) {
82 | return;
83 | }
84 |
85 | NSArray *operationsWithThisCategory = self.operations[category];
86 |
87 | NSUInteger index = [operationsWithThisCategory indexOfObject:operation];
88 | if (index != NSNotFound) {
89 | NSMutableArray *mutableArray = [operationsWithThisCategory mutableCopy];
90 | [mutableArray removeObjectAtIndex:index];
91 | operationsWithThisCategory = [NSArray arrayWithArray:mutableArray];
92 | self.operations[category] = operationsWithThisCategory;
93 | }
94 | }
95 |
96 |
97 | #pragma mark - Lifecycle
98 | #pragma mark -
99 |
100 | + (OPExclusivityController *)sharedExclusivityController
101 | {
102 | static OPExclusivityController *_sharedInstance = nil;
103 | static dispatch_once_t onceToken;
104 | dispatch_once(&onceToken, ^{
105 | _sharedInstance = [[OPExclusivityController alloc] init];
106 | });
107 |
108 | return _sharedInstance;
109 | }
110 |
111 | - (instancetype)init
112 | {
113 | self = [super init];
114 | if (!self) {
115 | return nil;
116 | }
117 |
118 | _serialQueue = dispatch_queue_create("Operative.ExclusivityController", DISPATCH_QUEUE_SERIAL);
119 | _operations = [[NSMutableDictionary alloc] init];
120 |
121 | return self;
122 | }
123 |
124 | @end
125 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Observers/OPBackgroundObserver.m:
--------------------------------------------------------------------------------
1 | // OPBackgroundObserver.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | #import "OPBackgroundObserver.h"
24 |
25 |
26 | @interface OPBackgroundObserver ()
27 |
28 | @property (assign, nonatomic) UIBackgroundTaskIdentifier identifier;
29 |
30 | @property (assign, nonatomic, getter=isInBackground) BOOL inBackground;
31 |
32 |
33 | @end
34 |
35 |
36 | @implementation OPBackgroundObserver
37 |
38 |
39 | #pragma mark - Start / End Background Task
40 | #pragma mark -
41 |
42 | - (void)startBackgroundTask
43 | {
44 | if ([self identifier] != UIBackgroundTaskInvalid) {
45 | return;
46 | }
47 |
48 | UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithName:NSStringFromClass([OPBackgroundObserver class])
49 | expirationHandler:^{
50 | [self endBackgroundTask];
51 | }];
52 | [self setIdentifier:identifier];
53 | }
54 |
55 | - (void)endBackgroundTask
56 | {
57 | if ([self identifier] == UIBackgroundTaskInvalid) {
58 | return;
59 | }
60 |
61 | [[UIApplication sharedApplication] endBackgroundTask:[self identifier]];
62 | [self setIdentifier:UIBackgroundTaskInvalid];
63 | }
64 |
65 |
66 | #pragma mark - Notification Actions
67 | #pragma mark -
68 |
69 | - (void)didEnterBackground:(NSNotification *)notification
70 | {
71 | if (![self isInBackground]) {
72 | [self setInBackground:YES];
73 | [self startBackgroundTask];
74 | }
75 | }
76 |
77 | - (void)didEnterForeground:(NSNotification *)notification
78 | {
79 | if ([self isInBackground]) {
80 | [self setInBackground:NO];
81 | [self endBackgroundTask];
82 | }
83 | }
84 |
85 |
86 | #pragma mark - OPOperationObserver Protocol
87 | #pragma mark -
88 |
89 | - (void)operationDidStart:(OPOperation *)operation
90 | {
91 | // No-op
92 | }
93 |
94 | - (void)operation:(OPOperation *)operation didProduceOperation:(NSOperation *)newOperation
95 | {
96 | // No-op
97 | }
98 |
99 | - (void)operation:(OPOperation *)operation didFinishWithErrors:(NSArray *)errors
100 | {
101 | [self endBackgroundTask];
102 | }
103 |
104 |
105 | #pragma mark - Lifecycle
106 | #pragma mark -
107 |
108 | - (instancetype)init
109 | {
110 | self = [super init];
111 | if (!self) {
112 | return nil;
113 | }
114 |
115 | // We need to know when the application moves to/from the background.
116 | NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
117 | [center addObserver:self selector:@selector(didEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
118 | [center addObserver:self selector:@selector(didEnterForeground:) name:UIApplicationDidBecomeActiveNotification object:nil];
119 |
120 | _identifier = UIBackgroundTaskInvalid;
121 | _inBackground = ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground);
122 |
123 | // If we're in the background already, immediately begin the background task.
124 | if (_inBackground) {
125 | [self startBackgroundTask];
126 | }
127 |
128 | return self;
129 | }
130 |
131 | - (void)dealloc
132 | {
133 | [[NSNotificationCenter defaultCenter] removeObserver:self];
134 | }
135 |
136 | @end
137 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/OPOperation.h:
--------------------------------------------------------------------------------
1 | // OPOperation.h
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 | @protocol OPOperationObserver;
25 | @protocol OPOperationCondition;
26 |
27 |
28 | /**
29 | * `OPOperation` is a subclass of `NSOperation`
30 | * from which all other operations within `Operative` should be derived.
31 | * This class adds both Conditions and Observers, which allow the operation
32 | * to define extended readiness requirements, as well as notify many
33 | * interested parties about interesting operation state changes
34 | */
35 | @interface OPOperation : NSOperation
36 |
37 | /**
38 | * `BOOL` value indicating if the operation is considered user
39 | * initiated. Changing this value will change the operations quality
40 | * of service to `NSOperationQualityOfServiceUserInitiated` or
41 | * `NSOperationQualityOfServiceUtility` accordingly
42 | */
43 | @property (assign, nonatomic) BOOL userInitiated;
44 |
45 | /**
46 | * An array of objects that conform to the `OPOperationCondition`
47 | * protocol. Before execution of the operation, conditions will be
48 | * checked and if met the operation will execute as normal.
49 | *
50 | * Array should not be manipulated directly.
51 | *
52 | * @see -addCondition:
53 | */
54 | @property (strong, nonatomic, readonly) NSMutableArray *conditions;
55 |
56 |
57 | ///---------------------------------------------
58 | /// @name Conditions, Observers and Dependencies
59 | ///---------------------------------------------
60 |
61 | - (void)addCondition:(id )condition;
62 |
63 | - (void)addObserver:(id )observer;
64 |
65 | - (void)addDependency:(NSOperation *)operation;
66 |
67 |
68 | ///---------------------------------
69 | /// @name Execution and Cancellation
70 | ///---------------------------------
71 |
72 | /**
73 | * Indicates that the Operation can now begin to evaluate
74 | * readiness conditions, if appropriate.
75 | */
76 | - (void)willEnqueue;
77 |
78 | /**
79 | * -execute is the entry point of execution for all `OPOperation` subclasses.
80 | * If you subclass `OPOperation` and wish to customize its execution, you
81 | * would do so by overriding the -execute method.
82 | * At some point, your `OPOperation` subclass must call one of the "finish"
83 | * methods defined below; this is how you indicate that your operation has
84 | * finished its execution, and that operations dependent on yours can
85 | * re-evaluate their readiness state.
86 | */
87 | - (void)execute;
88 |
89 | - (void)cancelWithError:(NSError *)error;
90 |
91 | - (void)produceOperation:(NSOperation *)operation;
92 |
93 | /*
94 | * This is a convenience method to simplify calling the actual
95 | * -finishWithErrors: method, when an error isn't present
96 | *
97 | * @see -finishWithError:
98 | */
99 | - (void)finish;
100 |
101 | /*
102 | * Most operations may finish with a single error, if they have one at all.
103 | * This is a convenience method to simplify the calling of -finishWithErrors:
104 | * -finishWithError: is useful if you wish to finish with an error provided
105 | * by the system frameworks / when a single error is present.
106 | *
107 | * @see -finish
108 | * @see -finishWithErrors:
109 | */
110 | - (void)finishWithError:(NSError *)error;
111 |
112 | /*
113 | * Called once an `OPOperation` has finished. This method transitions the
114 | * operation to a state of finishing, informs any observers that the operation
115 | * finished, and then transitions to a state of finished
116 | *
117 | * @see -finish
118 | * @see -finishWithError:
119 | */
120 | - (void)finishWithErrors:(NSArray *)errors;
121 |
122 | /*
123 | * Subclasses may override -finishedWithErrors: if they wish to react to the operation
124 | * finishing with errors.
125 | */
126 | - (void)finishedWithErrors:(NSArray *)errors;
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Operations/UI/OPAlertOperation.m:
--------------------------------------------------------------------------------
1 | // OPAlertOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #if TARGET_OS_IPHONE
23 |
24 | #import "OPAlertOperation.h"
25 | #import "OPOperationConditionMutuallyExclusive.h"
26 |
27 |
28 | @interface OPAlertOperation ()
29 |
30 | @property (strong, nonatomic) UIAlertController *alertController;
31 |
32 | @property (strong, nonatomic) UIViewController *presentationContext;
33 |
34 | @end
35 |
36 |
37 | @implementation OPAlertOperation
38 |
39 |
40 | #pragma mark - Add Action
41 | #pragma mark -
42 |
43 | - (void)addAction:(NSString *)title
44 | style:(UIAlertActionStyle)style
45 | handler:(void (^)(OPAlertOperation *alertOperation))handler;
46 | {
47 | __weak __typeof__(self) weakSelf = self;
48 | UIAlertAction *action = [UIAlertAction actionWithTitle:title style:style handler:^(UIAlertAction *action) {
49 | __typeof__(self) strongSelf = weakSelf;
50 |
51 | if (handler) {
52 | handler(strongSelf);
53 | }
54 |
55 | [strongSelf finish];
56 | }];
57 |
58 | [self.alertController addAction:action];
59 | }
60 |
61 |
62 | #pragma mark - Overrides
63 | #pragma mark -
64 |
65 | - (void)execute
66 | {
67 | if (![self presentationContext]) {
68 | [self finish];
69 | return;
70 | }
71 |
72 | dispatch_async(dispatch_get_main_queue(), ^{
73 | if([self isCancelled]) {
74 | return;
75 | }
76 |
77 | if ([self.alertController.actions count] == 0) {
78 | [self addAction:@"OK" style:UIAlertActionStyleDefault handler:nil];
79 | }
80 |
81 | [self.presentationContext presentViewController:[self alertController] animated:YES completion:nil];
82 | });
83 | }
84 |
85 | - (void)cancel
86 | {
87 | dispatch_async(dispatch_get_main_queue(), ^{
88 | if(self.alertController.presentingViewController)
89 | {
90 | [self.alertController dismissViewControllerAnimated:YES completion:^{
91 | [super cancel];
92 | }];
93 | }
94 | else
95 | {
96 | [super cancel];
97 | }
98 | });
99 | }
100 |
101 |
102 | #pragma mark - Getters / Setters
103 | #pragma mark -
104 |
105 | - (NSString *)title
106 | {
107 | return [self.alertController title];
108 | }
109 |
110 | - (void)setTitle:(NSString *)title
111 | {
112 | [self.alertController setTitle:[title copy]];
113 | }
114 |
115 | - (NSString *)message
116 | {
117 | return [self.alertController message];
118 | }
119 |
120 | - (void)setMessage:(NSString *)message
121 | {
122 | [self.alertController setMessage:[message copy]];
123 | }
124 |
125 |
126 | #pragma mark - Lifecycle
127 | #pragma mark -
128 |
129 | - (instancetype)initWithPresentationContext:(UIViewController *)presentationContext
130 | {
131 | self = [self initWithPresentationContext:presentationContext
132 | preferredStyle:UIAlertControllerStyleActionSheet];
133 | if (!self) {
134 | return nil;
135 | }
136 |
137 | return self;
138 | }
139 |
140 | - (instancetype)initWithPresentationContext:(UIViewController *)presentationContext
141 | preferredStyle:(UIAlertControllerStyle)preferredStyle
142 | {
143 | self = [super init];
144 |
145 | if (!self) {
146 | return nil;
147 | }
148 |
149 | _alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:preferredStyle];
150 |
151 | _presentationContext = presentationContext ?: [[[UIApplication sharedApplication] keyWindow] rootViewController];
152 |
153 | [self addCondition:[OPOperationConditionMutuallyExclusive alertPresentationExclusivity]];
154 |
155 | /**
156 | * This operation modifies the view controller hierarchy.
157 | * Doing this while other such operations are executing can lead to
158 | * inconsistencies in UIKit. So, let's make them mutally exclusive.
159 | */
160 | [self addCondition:[OPOperationConditionMutuallyExclusive mutuallyExclusiveWith:[UIViewController class]]];
161 |
162 | return self;
163 | }
164 |
165 | @end
166 |
167 | #endif
168 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Operations/Misc/OPGroupOperation.m:
--------------------------------------------------------------------------------
1 | // OPGroupOperation.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPGroupOperation.h"
23 | #import "OPOperationQueue.h"
24 |
25 |
26 | @interface OPGroupOperation()
27 |
28 | - (instancetype)init NS_DESIGNATED_INITIALIZER;
29 |
30 | /**
31 | * Common initialized elements used in both `-init` & `-initWithOperations:`
32 | */
33 | - (void)commonInit;
34 |
35 | @property (strong, nonatomic) OPOperationQueue *internalQueue;
36 | @property (strong, nonatomic) NSBlockOperation *finishingOperation;
37 |
38 | @property (strong, nonatomic) NSMutableArray *aggregatedErrors;
39 |
40 | @end
41 |
42 |
43 | @implementation OPGroupOperation
44 |
45 | #pragma mark - Debugging
46 | #pragma mark -
47 |
48 | - (NSString *)debugDescription
49 | {
50 | NSMutableString *mutableString = [[NSMutableString alloc] init];
51 | NSString *description = [super debugDescription];
52 | NSString *result;
53 |
54 | NSArray *lines = [[self.internalQueue debugDescription] componentsSeparatedByString:@"\n"];
55 |
56 | for(NSString *str in lines)
57 | {
58 | [mutableString appendFormat:@"\t%@\n", str];
59 | }
60 |
61 | result = [description stringByAppendingFormat:@"\n%@", mutableString];
62 |
63 | return [result stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
64 | }
65 |
66 | #pragma mark -
67 | #pragma mark -
68 |
69 | - (void)addOperation:(NSOperation *)operation
70 | {
71 | [self.internalQueue addOperation:operation];
72 | }
73 |
74 | - (void)addOperations:(NSArray *)operations
75 | {
76 | [self.internalQueue addOperations:operations waitUntilFinished:NO];
77 | }
78 |
79 | - (void)aggregateError:(NSError *)error
80 | {
81 | [self.aggregatedErrors addObject:error];
82 | }
83 |
84 | - (void)operationDidFinish:(NSOperation *)operation withErrors:(NSArray *)errors
85 | {
86 | // No-op
87 | // For use by subclass.
88 | }
89 |
90 |
91 | #pragma mark - Overrides
92 | #pragma mark -
93 |
94 | - (void)cancel
95 | {
96 | [self.internalQueue cancelAllOperations];
97 | [super cancel];
98 | }
99 |
100 | - (void)execute
101 | {
102 | [self.internalQueue setSuspended:NO];
103 | [self.internalQueue addOperation:self.finishingOperation];
104 | }
105 |
106 |
107 | #pragma mark - OPOperationQueueDelegate
108 | #pragma mark -
109 |
110 | - (void)operationQueue:(OPOperationQueue *)operationQueue willAddOperation:(NSOperation *)operation
111 | {
112 | NSAssert(![self.finishingOperation isFinished] && ![self.finishingOperation isExecuting], @"Cannot add new operations to a group after the group has completed");
113 |
114 | if ([self finishingOperation] != operation) {
115 | [self.finishingOperation addDependency:operation];
116 | }
117 | }
118 |
119 | - (void)operationQueue:(OPOperationQueue *)operationQueue operationDidFinish:(NSOperation *)operation withErrors:(NSArray *)errors
120 | {
121 | [self.aggregatedErrors addObjectsFromArray:errors];
122 |
123 | if ([self finishingOperation] == operation) {
124 | [self.internalQueue setSuspended:YES];
125 | [self finishWithErrors:[self aggregatedErrors]];
126 | } else {
127 | [self operationDidFinish:operation withErrors:errors];
128 | }
129 | }
130 |
131 |
132 | #pragma mark - Lifecycle
133 | #pragma mark -
134 |
135 | - (instancetype)init
136 | {
137 | self = [super init];
138 | if (!self) {
139 | return nil;
140 | }
141 |
142 | [self commonInit];
143 |
144 | return self;
145 | }
146 |
147 | - (instancetype)initWithOperations:(NSArray *)operations
148 | {
149 | self = [super init];
150 | if (!self) {
151 | return nil;
152 | }
153 |
154 | [self commonInit];
155 |
156 | for (NSOperation *operation in operations) {
157 | [_internalQueue addOperation:operation];
158 | }
159 |
160 | return self;
161 | }
162 |
163 |
164 | #pragma mark - Private
165 | #pragma mark -
166 |
167 | - (void)commonInit
168 | {
169 | OPOperationQueue *queue = [[OPOperationQueue alloc] init];
170 | [queue setSuspended:YES];
171 | [queue setDelegate:self];
172 |
173 | _internalQueue = queue;
174 |
175 | _finishingOperation = [NSBlockOperation blockOperationWithBlock:^{}];
176 |
177 | _aggregatedErrors = [[NSMutableArray alloc] init];
178 | }
179 |
180 | @end
181 |
--------------------------------------------------------------------------------
/Pod/Classes/Core/Conditions/OPReachabilityCondition.m:
--------------------------------------------------------------------------------
1 | // OPReachabilityCondition.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPReachabilityCondition.h"
23 |
24 | #import "NSError+Operative.h"
25 |
26 | #import
27 |
28 |
29 | static NSString *const kOPOperationHostKey = @"OperationHost";
30 |
31 |
32 | @interface OPReachabilityController : NSObject
33 |
34 | + (OPReachabilityController *)sharedInstance;
35 |
36 | #if OS_OBJECT_USE_OBJC
37 | @property (strong, nonatomic) dispatch_queue_t reachabilityQueue;
38 | #else
39 | @property (assign, nonatomic) dispatch_queue_t reachabilityQueue;
40 | #endif
41 |
42 | @property (strong, nonatomic) NSMutableDictionary *reachabilityRefs;
43 |
44 | - (void)requestReachabilityWithURL:(NSURL *)url
45 | completionHandler:(void (^)(BOOL reachable))completionHandler;
46 |
47 | @end
48 |
49 |
50 | @interface OPReachabilityCondition ()
51 |
52 | @property (copy, nonatomic) NSURL *host;
53 |
54 | @end
55 |
56 |
57 |
58 | @implementation OPReachabilityCondition
59 |
60 |
61 | #pragma mark - OPOperationCondition Protocol
62 | #pragma mark -
63 |
64 | - (NSString *)name
65 | {
66 | return @"Reachability";
67 | }
68 |
69 | - (BOOL)isMutuallyExclusive
70 | {
71 | return NO;
72 | }
73 |
74 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
75 | {
76 | return nil;
77 | }
78 |
79 | - (void)evaluateConditionForOperation:(OPOperation *)operation
80 | completion:(void (^)(OPOperationConditionResultStatus, NSError *))completion
81 | {
82 | [[OPReachabilityController sharedInstance] requestReachabilityWithURL:[self host]
83 | completionHandler:^(BOOL reachable) {
84 | if (reachable) {
85 | completion(OPOperationConditionResultStatusSatisfied, nil);
86 | } else {
87 | NSError *error = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:@{
88 | kOPOperationConditionKey : [self name],
89 | kOPOperationHostKey : [self host]
90 | }];
91 | completion(OPOperationConditionResultStatusFailed, error);
92 | }
93 | }];
94 | }
95 |
96 |
97 | #pragma mark - Lifecycle
98 | #pragma mark -
99 |
100 | - (instancetype)initWithHost:(NSURL *)host
101 | {
102 | self = [super init];
103 | if (!self) {
104 | return nil;
105 | }
106 |
107 | _host = [host copy];
108 |
109 | return self;
110 | }
111 |
112 | @end
113 |
114 |
115 | @implementation OPReachabilityController
116 |
117 |
118 | #pragma mark - Reachability
119 | #pragma mark -
120 |
121 | - (void)requestReachabilityWithURL:(NSURL *)url
122 | completionHandler:(void (^)(BOOL reachable))completionHandler
123 | {
124 | NSString *host = [url host];
125 |
126 | if (!host) {
127 | completionHandler(NO);
128 | return;
129 | }
130 |
131 | dispatch_async([self reachabilityQueue], ^{
132 | SCNetworkReachabilityRef ref = (__bridge SCNetworkReachabilityRef)(self.reachabilityRefs[host]);
133 |
134 | if (!ref) {
135 | ref = SCNetworkReachabilityCreateWithName(nil, [host UTF8String]);
136 | }
137 |
138 | if (ref) {
139 | self.reachabilityRefs[host] = (__bridge id)(ref);
140 |
141 | BOOL reachable = NO;
142 | SCNetworkReachabilityFlags flags = 0;
143 | if (SCNetworkReachabilityGetFlags(ref, &flags) != 0) {
144 | reachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
145 | }
146 | completionHandler(reachable);
147 | } else {
148 | completionHandler(NO);
149 | }
150 | });
151 | }
152 |
153 |
154 | #pragma mark - Lifecycle
155 | #pragma mark -
156 |
157 | + (OPReachabilityController *)sharedInstance
158 | {
159 | static OPReachabilityController *_sharedInstance = nil;
160 | static dispatch_once_t onceToken;
161 | dispatch_once(&onceToken, ^{
162 | _sharedInstance = [[OPReachabilityController alloc] init];
163 | });
164 |
165 | return _sharedInstance;
166 | }
167 |
168 | - (instancetype)init
169 | {
170 | self = [super init];
171 | if (!self) {
172 | return nil;
173 | }
174 |
175 | _reachabilityQueue = dispatch_queue_create("Operative.Reachability", DISPATCH_QUEUE_SERIAL);
176 | _reachabilityRefs = [[NSMutableDictionary alloc] init];
177 |
178 | return self;
179 | }
180 |
181 | @end
182 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Observers/OPNetworkObserver.m:
--------------------------------------------------------------------------------
1 | // OPNetworkObserver.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPNetworkObserver.h"
23 |
24 |
25 | /**
26 | * Essentially a cancellable `dispatch_after`.
27 | */
28 | @interface OPTimer : NSObject
29 |
30 | @property (assign, nonatomic, getter=isCancelled) BOOL cancelled;
31 |
32 | @property (copy, nonatomic, readonly) dispatch_block_t handler;
33 |
34 | - (instancetype)initWithInterval:(NSTimeInterval)interval handler:(dispatch_block_t)handler NS_DESIGNATED_INITIALIZER;
35 |
36 | - (instancetype)init NS_UNAVAILABLE;
37 |
38 | - (void)cancel;
39 |
40 | @end
41 |
42 |
43 | /**
44 | * A singleton to manage a visual "reference count" on the network activity indicator.
45 | */
46 | @interface OPNetworkIndicatorController : NSObject
47 |
48 | + (OPNetworkIndicatorController *)sharedInstance;
49 |
50 | @property (assign, nonatomic) NSUInteger activityCount;
51 |
52 | @property (strong, nonatomic) OPTimer *visibilityTimer;
53 |
54 | - (void)networkActivityDidStart;
55 |
56 | - (void)networkActivityDidEnd;
57 |
58 | - (void)updateIndicatorVisibility;
59 |
60 | @end
61 |
62 |
63 | @implementation OPNetworkObserver
64 |
65 | - (void)operationDidStart:(OPOperation *)operation
66 | {
67 | dispatch_async(dispatch_get_main_queue(), ^{
68 | // Increment the network indicator's "reference count"
69 | [[OPNetworkIndicatorController sharedInstance] networkActivityDidStart];
70 | });
71 | }
72 |
73 | - (void)operation:(OPOperation *)operation didProduceOperation:(NSOperation *)newOperation {}
74 |
75 | - (void)operation:(OPOperation *)operation didFinishWithErrors:(NSArray *)errors
76 | {
77 | dispatch_async(dispatch_get_main_queue(), ^{
78 | // Decrement the network indicator's "reference count".
79 | [[OPNetworkIndicatorController sharedInstance] networkActivityDidEnd];
80 | });
81 | }
82 |
83 | @end
84 |
85 |
86 | @implementation OPNetworkIndicatorController
87 |
88 | + (OPNetworkIndicatorController *)sharedInstance
89 | {
90 | static OPNetworkIndicatorController *_sharedInstance = nil;
91 | static dispatch_once_t onceToken;
92 | dispatch_once(&onceToken, ^{
93 | _sharedInstance = [[OPNetworkIndicatorController alloc] init];
94 | });
95 |
96 | return _sharedInstance;
97 | }
98 |
99 | - (instancetype)init
100 | {
101 | self = [super init];
102 | if (!self) {
103 | return nil;
104 | }
105 |
106 | _activityCount = 0;
107 |
108 | return self;
109 | }
110 |
111 | - (void)networkActivityDidStart
112 | {
113 | NSAssert([NSThread isMainThread], @"Altering network activity indicator state can only be done on the main thread.");
114 | self.activityCount++;
115 |
116 | [self updateIndicatorVisibility];
117 | }
118 |
119 | - (void)networkActivityDidEnd
120 | {
121 | self.activityCount--;
122 |
123 | [self updateIndicatorVisibility];
124 | }
125 |
126 | - (void)updateIndicatorVisibility
127 | {
128 | if ([self activityCount] > 0) {
129 | [self showIndicator];
130 | } else {
131 | /*
132 | To prevent the indicator from flickering on and off, we delay the
133 | hiding of the indicator by one second. This provides the chance
134 | to come in and invalidate the timer before it fires.
135 | */
136 | OPTimer *timer = [[OPTimer alloc] initWithInterval:1.0f
137 | handler:^{
138 | [self hideIndicator];
139 | }];
140 | [self setVisibilityTimer:timer];
141 | }
142 | }
143 |
144 | - (void)cancelVisibilityTimer
145 | {
146 | if ([self visibilityTimer]) {
147 | [self.visibilityTimer cancel];
148 | [self setVisibilityTimer:nil];
149 | }
150 | }
151 |
152 | - (void)showIndicator
153 | {
154 | [self cancelVisibilityTimer];
155 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
156 | }
157 |
158 | - (void)hideIndicator
159 | {
160 | [self cancelVisibilityTimer];
161 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
162 | }
163 |
164 | @end
165 |
166 |
167 | @implementation OPTimer
168 |
169 | #pragma mark - Public
170 | #pragma mark -
171 |
172 | - (void)cancel
173 | {
174 | [self setCancelled:YES];
175 | }
176 |
177 | - (void)fire
178 | {
179 | if (![self isCancelled]) {
180 | self.handler();
181 | }
182 | }
183 |
184 |
185 | #pragma mark - Lifecycle
186 | #pragma mark -
187 |
188 | - (instancetype)initWithInterval:(NSTimeInterval)interval
189 | handler:(dispatch_block_t)handler
190 | {
191 | self = [super init];
192 | if (!self) {
193 | return nil;
194 | }
195 |
196 | _handler = [handler copy];
197 |
198 | dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC));
199 |
200 | __weak __typeof__(self) weakSelf = self;
201 | dispatch_after(when, dispatch_get_main_queue(), ^{
202 | __typeof__(self) strongSelf = weakSelf;
203 | [strongSelf fire];
204 | });
205 |
206 | return self;
207 | }
208 |
209 | @end
210 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/Conditions/OPOperationConditionUserNotification.m:
--------------------------------------------------------------------------------
1 | // OPOperationConditionUserNotification.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #if TARGET_OS_IPHONE
23 |
24 | #import "OPOperationConditionUserNotification.h"
25 | #import "OPOperationConditionMutuallyExclusive.h"
26 |
27 | #import "NSError+Operative.h"
28 | #import "UIUserNotificationSettings+Operative.h"
29 |
30 |
31 | NSString * const kCurrentSettings = @"CurrentUserNotificationSettings";
32 | NSString * const kDesiredSettings = @"DesiredUserNotificationSettings";
33 |
34 |
35 | #pragma mark - OPOperationConditionUserNotification Private
36 | #pragma mark -
37 |
38 | @interface OPOperationConditionUserNotification()
39 |
40 | @property (strong, nonatomic) UIUserNotificationSettings *settings;
41 | @property (strong, nonatomic) UIApplication *application;
42 | @property (assign, nonatomic) OPOperationConditionUserNotificationBehavior behavior;
43 |
44 | @end
45 |
46 |
47 | #pragma mark - OPUserNotificationPermissionOperation
48 | #pragma mark -
49 |
50 | @interface OPUserNotificationPermissionOperation : OPOperation
51 |
52 | @property (strong, nonatomic) UIUserNotificationSettings *settings;
53 | @property (strong, nonatomic) UIApplication *application;
54 | @property (assign, nonatomic) OPOperationConditionUserNotificationBehavior behavior;
55 |
56 | @end
57 |
58 |
59 | @implementation OPUserNotificationPermissionOperation
60 |
61 | - (instancetype)initWithSettings:(UIUserNotificationSettings *)settings
62 | application:(UIApplication *)application
63 | behavior:(OPOperationConditionUserNotificationBehavior)behavior
64 | {
65 | self = [super init];
66 | if (!self) {
67 | return nil;
68 | }
69 |
70 | _settings = settings;
71 | _application = application;
72 | _behavior = behavior;
73 |
74 | [self addCondition:[OPOperationConditionMutuallyExclusive alertPresentationExclusivity]];
75 |
76 | return self;
77 | }
78 |
79 | - (void)execute
80 | {
81 | dispatch_async(dispatch_get_main_queue(), ^{
82 | UIUserNotificationSettings *currentSettings = [self.application currentUserNotificationSettings];
83 | UIUserNotificationSettings *settingsToRegister;
84 |
85 | switch ([self behavior]) {
86 | case OPOperationConditionBehaviorMerge:
87 | settingsToRegister = [currentSettings settingsByMerging:[self settings]];
88 | break;
89 | case OPOperationConditionBehaviorReplace:
90 | default:
91 | settingsToRegister = [self settings];
92 | break;
93 | }
94 |
95 | [self.application registerUserNotificationSettings:settingsToRegister];
96 |
97 | [self finish];
98 | });
99 | }
100 |
101 | @end
102 |
103 |
104 | #pragma mark - OPOperationConditionUserNotification Implementation
105 | #pragma mark -
106 |
107 | @implementation OPOperationConditionUserNotification
108 |
109 | #pragma mark - Lifecycle
110 | #pragma mark -
111 |
112 | - (instancetype)initWithSettings:(UIUserNotificationSettings *)settings application:(UIApplication *)application
113 | {
114 | return [self initWithSettings:settings application:application behavior:OPOperationConditionBehaviorMerge];
115 | }
116 |
117 | - (instancetype) initWithSettings:(UIUserNotificationSettings *)settings application:(UIApplication *)application behavior:(OPOperationConditionUserNotificationBehavior)behavior
118 | {
119 | self = [super init];
120 | if (!self) {
121 | return nil;
122 | }
123 | _settings = settings;
124 | _application = application;
125 | _behavior = behavior;
126 |
127 | return self;
128 | }
129 |
130 |
131 | #pragma mark - OPOperationCondition
132 | #pragma mark -
133 |
134 | - (NSString *)name
135 | {
136 | return @"UserNotification";
137 | }
138 |
139 | - (BOOL)isMutuallyExclusive
140 | {
141 | return NO;
142 | }
143 |
144 | - (NSOperation *)dependencyForOperation:(OPOperation *)operation
145 | {
146 | return [[OPUserNotificationPermissionOperation alloc] initWithSettings:[self settings]
147 | application:[self application]
148 | behavior:[self behavior]];
149 | }
150 |
151 | - (void)evaluateConditionForOperation:(OPOperation *)operation
152 | completion:(void (^)(OPOperationConditionResultStatus result, NSError *error))completion
153 | {
154 | // Satisfied until not
155 | OPOperationConditionResultStatus result = OPOperationConditionResultStatusSatisfied;
156 |
157 | NSError *error = nil;
158 |
159 | UIUserNotificationSettings *current = [self.application currentUserNotificationSettings];
160 |
161 | if ([current containsSettings:[self settings]]) {
162 | // No-op
163 | } else {
164 | NSDictionary *userInfo = @{
165 | kOPOperationConditionKey : NSStringFromClass([self class]),
166 | kCurrentSettings : current ? : [NSNull null],
167 | kDesiredSettings : [self settings]
168 | };
169 | error = [NSError errorWithCode:OPOperationErrorCodeConditionFailed userInfo:userInfo];
170 | result = OPOperationConditionResultStatusFailed;
171 | }
172 |
173 | completion(result, error);
174 | }
175 |
176 | @end
177 |
178 | #endif
--------------------------------------------------------------------------------
/Example/Tests/CategoriesTests.m:
--------------------------------------------------------------------------------
1 | // CategoriesTests.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import
23 |
24 | #import
25 | #import
26 | #import
27 | #import
28 |
29 | @interface CategoriesTests : XCTestCase
30 |
31 | @end
32 |
33 | @implementation CategoriesTests
34 |
35 | - (void)setUp {
36 | [super setUp];
37 | // Put setup code here. This method is called before the invocation of each test method in the class.
38 | }
39 |
40 | - (void)tearDown {
41 | // Put teardown code here. This method is called after the invocation of each test method in the class.
42 | [super tearDown];
43 | }
44 |
45 | #pragma mark - NSError category
46 | #pragma mark -
47 |
48 | - (void)testCreateErrorWithCodeAndUserInfo {
49 | NSDictionary *userInfo = @{@"test": @(YES)};
50 | NSError *error = [NSError errorWithCode:1 userInfo:userInfo];
51 |
52 | XCTAssertEqual(error.code, 1);
53 | XCTAssertEqualObjects(error.userInfo, userInfo);
54 | XCTAssertEqualObjects(error.domain, kOPOperationErrorDomain);
55 | }
56 |
57 | - (void)testCreateErrorWithCode {
58 | NSError *error = [NSError errorWithCode:1];
59 |
60 | XCTAssertEqual(error.code, 1);
61 | XCTAssertEqualObjects(error.userInfo, @{});
62 | XCTAssertEqualObjects(error.domain, kOPOperationErrorDomain);
63 | }
64 |
65 | #pragma mark - NSMutableDictionary category
66 | #pragma mark -
67 |
68 | - (void)testCreateDictionaryFromSet {
69 | NSSet *set = [NSSet setWithObjects:@{@"key": @"1", @"value": @"1"}, @{@"key": @"2", @"value": @"2"}, nil];
70 |
71 | NSMutableDictionary *dict = [NSMutableDictionary sequence:set keyMapper:^(id obj) {
72 | return obj[@"key"];
73 | }];
74 |
75 | XCTAssertEqual(dict.allKeys.count, 2);
76 | XCTAssertEqual([[dict[@"1"] allKeys] count], 2);
77 | XCTAssertEqual([[dict[@"2"] allKeys] count], 2);
78 |
79 | XCTAssertEqualObjects(dict[@"1"][@"key"], @"1");
80 | XCTAssertEqualObjects(dict[@"1"][@"value"], @"1");
81 |
82 | XCTAssertEqualObjects(dict[@"2"][@"key"], @"2");
83 | XCTAssertEqualObjects(dict[@"2"][@"value"], @"2");
84 | }
85 |
86 | - (void)testCreateDictionaryFromArray {
87 | NSArray *array = @[@{@"key": @"1", @"value": @"1"}, @{@"key": @"2", @"value": @"2"}];
88 |
89 | NSMutableDictionary *dict = [NSMutableDictionary sequence:array keyMapper:^(id obj) {
90 | return obj[@"key"];
91 | }];
92 |
93 | XCTAssertEqual(dict.allKeys.count, 2);
94 | XCTAssertEqual([[dict[@"1"] allKeys] count], 2);
95 | XCTAssertEqual([[dict[@"2"] allKeys] count], 2);
96 |
97 | XCTAssertEqualObjects(dict[@"1"][@"key"], @"1");
98 | XCTAssertEqualObjects(dict[@"1"][@"value"], @"1");
99 |
100 | XCTAssertEqualObjects(dict[@"2"][@"key"], @"2");
101 | XCTAssertEqualObjects(dict[@"2"][@"value"], @"2");
102 | }
103 |
104 | #pragma mark - NSOperation category
105 | #pragma mark -
106 |
107 | - (void)testAddMultipleDependencies {
108 | NSOperation *operation = [[NSOperation alloc] init];
109 |
110 | NSMutableArray *array = [[NSMutableArray alloc] init];
111 | for (int i = 0; i < 10; i++)
112 | {
113 | [array addObject:[[NSOperation alloc] init]];
114 | }
115 |
116 | [operation addDependencies:array];
117 |
118 | XCTAssertEqual(operation.dependencies.count, 10);
119 | }
120 |
121 | - (void)testAddOriginalCompletionBlock {
122 | XCTestExpectation *expectation = [self expectationWithDescription:@"Should call original completion block"];
123 |
124 | NSOperation *operation = [[NSOperation alloc] init];
125 | operation.completionBlock = ^{
126 | [expectation fulfill];
127 | };
128 |
129 | [operation addCompletionBlock:^(void) {
130 | }];
131 |
132 | operation.completionBlock();
133 |
134 | [self waitForExpectationsWithTimeout:1 handler:nil];
135 | }
136 |
137 | - (void)testAddChainedCompletionBlock {
138 | XCTestExpectation *expectation = [self expectationWithDescription:@"Should call chained completion block"];
139 |
140 | NSOperation *operation = [[NSOperation alloc] init];
141 | operation.completionBlock = ^{
142 |
143 | };
144 |
145 | [operation addCompletionBlock:^(void) {
146 | [expectation fulfill];
147 | }];
148 |
149 | operation.completionBlock();
150 |
151 | [self waitForExpectationsWithTimeout:1 handler:nil];
152 | }
153 |
154 | #pragma mark - UIUserNotificationSettings category
155 | #pragma mark -
156 |
157 | - (void)testUserNotificationSettings {
158 | UIUserNotificationSettings *settings1;
159 | UIUserNotificationSettings *settings2;
160 |
161 | // All
162 | settings1 = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
163 | // All minus alert
164 | settings2 = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil];
165 |
166 | XCTAssertTrue([settings1 containsSettings:settings2]);
167 | XCTAssertFalse([settings2 containsSettings:settings1]);
168 |
169 | // All
170 | settings1 = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
171 | // All minus sound
172 | settings2 = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert) categories:nil];
173 | XCTAssertTrue([settings1 containsSettings:settings2]);
174 | XCTAssertFalse([settings2 containsSettings:settings1]);
175 |
176 | // All
177 | settings1 = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
178 | // All minus Badge
179 | settings2 = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
180 | XCTAssertTrue([settings1 containsSettings:settings2]);
181 | XCTAssertFalse([settings2 containsSettings:settings1]);
182 | }
183 |
184 | @end
185 |
--------------------------------------------------------------------------------
/Example/Operative/OPViewController.m:
--------------------------------------------------------------------------------
1 | // OPViewController.m
2 | // Copyright (c) 2015 Tom Wilson
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | #import "OPViewController.h"
23 | #import
24 |
25 | #import "GroupOperationTest.h"
26 |
27 | @interface OPViewController ()
28 |
29 | @property (strong, nonatomic) OPOperationQueue *queue;
30 |
31 | @end
32 |
33 | @implementation OPViewController
34 |
35 | - (void)viewDidLoad
36 | {
37 | [super viewDidLoad];
38 | // Do any additional setup after loading the view, typically from a nib.
39 |
40 | OPDelayOperation *delay = [[OPDelayOperation alloc] initWithTimeInterval:10.0f];
41 | [self.queue addOperation:delay];
42 |
43 | // Alert options - one at a time!
44 | for (NSUInteger i = 0; i < 5; i++) {
45 | OPAlertOperation *operation = [[OPAlertOperation alloc] initWithPresentationContext:self];
46 | operation.title = [NSString stringWithFormat:@"Alert #%lu", (unsigned long)i];
47 | [operation addDependency:delay];
48 | [self.queue addOperation:operation];
49 | }
50 |
51 | // [delay cancel];
52 |
53 | //
54 | // Block operations
55 | //
56 | // Background block
57 | OPBlockOperation *background = [[OPBlockOperation alloc] initWithBlock:^(void(^completion)(void)) {
58 | NSLog(@"Background block operation on main thread: %i", [NSThread isMainThread]);
59 | completion();
60 | }];
61 | [background addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
62 | NSLog(@"Background block operation started!");
63 | } produceHandler:nil
64 | finishHandler:^(OPOperation *operation, NSArray *errors) {
65 | NSLog(@"Background block operation finished!");
66 | }]];
67 |
68 | // Main thread block
69 | OPBlockOperation *mainThread = [[OPBlockOperation alloc] initWithMainQueueBlock:^{
70 | NSLog(@"Main Thread block operation on main thread: %i", [NSThread isMainThread]);
71 | }];
72 | [mainThread addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
73 | NSLog(@"Main Thread block operation started!");
74 | } produceHandler:nil
75 | finishHandler:^(OPOperation *operation, NSArray *errors) {
76 | NSLog(@"Main Thread block operation finished!");
77 | }]];
78 |
79 | // Start them
80 | [self.queue addOperation:background];
81 | [self.queue addOperation:mainThread];
82 |
83 | NSURLSessionConfiguration *sessionConfig =
84 | [NSURLSessionConfiguration defaultSessionConfiguration];
85 |
86 | // 1
87 | sessionConfig.allowsCellularAccess = YES;
88 |
89 | // 2
90 | [sessionConfig setHTTPAdditionalHeaders:
91 | @{@"Accept": @"application/json"}];
92 |
93 | // 3
94 | sessionConfig.timeoutIntervalForRequest = 30.0;
95 | sessionConfig.timeoutIntervalForResource = 60.0;
96 | sessionConfig.HTTPMaximumConnectionsPerHost = 1;
97 |
98 | NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
99 |
100 | NSURLSessionTask *sessionTask = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://api.github.com/repos/elixir-lang/elixir/issues"]]
101 | completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
102 | // NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
103 | // NSLog(@"%@", dict.description);
104 | }];
105 |
106 | OPURLSessionTaskOperation *urlOperation = [[OPURLSessionTaskOperation alloc] initWithTask:sessionTask];
107 |
108 | [urlOperation addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
109 | NSLog(@"URL Operation started!");
110 | }
111 | produceHandler:^(OPOperation *operation, NSOperation *newOperation) {
112 | } finishHandler:^(OPOperation *operation, NSArray *errors) {
113 | NSLog(@"URL Operation finished");
114 | NSLog(@"%@", sessionTask.response);
115 | }]];
116 |
117 | [self.queue addOperation:urlOperation];
118 |
119 |
120 | // Group operation
121 |
122 | GroupOperationTest *groupTest = [[GroupOperationTest alloc] init];
123 | [groupTest addObserver:[[OPBlockObserver alloc] initWithStartHandler:^(OPOperation *operation) {
124 | NSLog(@"Group operation started");
125 | } produceHandler:^(OPOperation *operation, NSOperation *newOperation) {
126 | NSLog(@"Group operation produced operation: %@", operation);
127 | } finishHandler:^(OPOperation *operation, NSArray *errors) {
128 | NSLog(@"Group operation completed!");
129 | }]];
130 | [self.queue addOperation:groupTest];
131 |
132 |
133 |
134 |
135 |
136 | // Location Test
137 | OPLocationOperation *locationOperation = [[OPLocationOperation alloc] initWithAccuracy:1000.f
138 | locationHandler:^(CLLocation *location) {
139 | NSLog(@"Got location: %f, %f", location.coordinate.latitude, location.coordinate.longitude);
140 | }];
141 |
142 | [self.queue addOperation:locationOperation];
143 | }
144 |
145 | - (void)didReceiveMemoryWarning
146 | {
147 | [super didReceiveMemoryWarning];
148 | // Dispose of any resources that can be recreated.
149 | }
150 |
151 | #pragma mark - Properties
152 |
153 | - (OPOperationQueue *) queue
154 | {
155 | if (!_queue)
156 | {
157 | _queue = [[OPOperationQueue alloc] init];
158 | _queue.maxConcurrentOperationCount = 5;
159 | }
160 | return _queue;
161 |
162 | }
163 | @end
164 |
--------------------------------------------------------------------------------