├── .gitignore ├── .travis.yml ├── DRAsyncOperations.podspec ├── DRAsyncOperations.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── DRAsyncOperations Mac.xcscheme │ ├── DRAsyncOperations iOS.xcscheme │ ├── DRAsyncOperations tvOS.xcscheme │ └── DRAsyncOperations watchOS.xcscheme ├── DRAsyncOperations ├── DRAsyncBlockOperation.h ├── DRAsyncBlockOperation.m ├── DRAsyncOperation.h ├── DRAsyncOperation.m ├── DRAsyncOperationSubclass.h ├── DRAsyncOperations.h └── Supporting Files │ └── Info.plist ├── DRAsyncOperationsTests ├── DRAsyncBlockOperationTests.m ├── DRAsyncOperationTests.swift └── Supporting Files │ ├── DRAsyncOperationsTests-Bridging-Header.h │ └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ######################################## 2 | # OSX ################################## 3 | ######################################## 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | ######################################## 32 | # Xcode ################################ 33 | ######################################## 34 | 35 | build/ 36 | *.pbxuser 37 | !default.pbxuser 38 | *.mode1v3 39 | !default.mode1v3 40 | *.mode2v3 41 | !default.mode2v3 42 | *.perspectivev3 43 | !default.perspectivev3 44 | xcuserdata 45 | *.xccheckout 46 | *.moved-aside 47 | DerivedData 48 | *.hmap 49 | *.ipa 50 | *.xcuserstate 51 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7.2 3 | 4 | before_install: 5 | - gem install cocoapods 6 | - gem install xcpretty 7 | 8 | script: 9 | - set -o pipefail 10 | - pod lib lint --allow-warnings 11 | - xcodebuild -scheme "DRAsyncOperations Mac" test | xcpretty 12 | - xcodebuild -scheme "DRAsyncOperations iOS" -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 6s" test | xcpretty 13 | - xcodebuild -scheme "DRAsyncOperations tvOS" -sdk appletvsimulator -destination "platform=tvOS Simulator,name=Apple TV 1080p" test | xcpretty 14 | - xcodebuild -scheme "DRAsyncOperations watchOS" -sdk watchsimulator -destination "platform=watchOS Simulator,name=Apple Watch - 38mm" build | xcpretty 15 | -------------------------------------------------------------------------------- /DRAsyncOperations.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'DRAsyncOperations' 3 | spec.version = '1.0.1' 4 | spec.license = { :type => 'MIT' } 5 | spec.summary = 'Implementation of a concurrent NSOperation to abstract and help the creation of asynchronous operations.' 6 | spec.homepage = 'https://github.com/dmcrodrigues/DRAsyncOperations' 7 | spec.authors = { 'David Rodrigues' => 'https://twitter.com/dmcrodrigues' } 8 | spec.source = { :git => 'https://github.com/dmcrodrigues/DRAsyncOperations.git', :tag => spec.version.to_s } 9 | spec.requires_arc = true 10 | 11 | spec.public_header_files = 'DRAsyncOperations/DRAsyncOperations.h' 12 | spec.source_files = 'DRAsyncOperations/*.{h,m}' 13 | 14 | spec.ios.deployment_target = '7.0' 15 | spec.osx.deployment_target = '10.9' 16 | spec.watchos.deployment_target = '2.0' 17 | spec.tvos.deployment_target = '9.0' 18 | end 19 | -------------------------------------------------------------------------------- /DRAsyncOperations.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7D85D6CE1C48377200548F21 /* DRAsyncOperations.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D85D6C41C48377200548F21 /* DRAsyncOperations.framework */; }; 11 | 7D85D6E81C48381A00548F21 /* DRAsyncBlockOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F9B1B4B25D800947482 /* DRAsyncBlockOperationTests.m */; }; 12 | 7D85D6E91C48381A00548F21 /* DRAsyncOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F9C1B4B25D800947482 /* DRAsyncOperationTests.swift */; }; 13 | 7D85D6EB1C48386900548F21 /* DRAsyncOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F911B4B25AC00947482 /* DRAsyncOperation.m */; }; 14 | 7D85D6EE1C48386900548F21 /* DRAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F971B4B25BF00947482 /* DRAsyncBlockOperation.m */; }; 15 | 7D85D6EF1C48387C00548F21 /* DRAsyncOperationSubclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F921B4B25AC00947482 /* DRAsyncOperationSubclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | 7D85D6F01C48388300548F21 /* DRAsyncOperationSubclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F921B4B25AC00947482 /* DRAsyncOperationSubclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; 17 | 7D85D6F11C48388700548F21 /* DRAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F961B4B25BF00947482 /* DRAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18 | 7D85D6F21C48388800548F21 /* DRAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F961B4B25BF00947482 /* DRAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | 7D85D6F31C48388B00548F21 /* DRAsyncOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F901B4B25AC00947482 /* DRAsyncOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | 7D85D6F41C48388C00548F21 /* DRAsyncOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F901B4B25AC00947482 /* DRAsyncOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | 7D85D6F51C48389100548F21 /* DRAsyncOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F791B4B259200947482 /* DRAsyncOperations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 22 | 7D85D6F61C48389100548F21 /* DRAsyncOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F791B4B259200947482 /* DRAsyncOperations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23 | 7D85D6F71C4838B100548F21 /* DRAsyncOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F911B4B25AC00947482 /* DRAsyncOperation.m */; }; 24 | 7D85D6F81C4838B100548F21 /* DRAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F971B4B25BF00947482 /* DRAsyncBlockOperation.m */; }; 25 | 7D9C8F7A1B4B259200947482 /* DRAsyncOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F791B4B259200947482 /* DRAsyncOperations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | 7D9C8F801B4B259200947482 /* DRAsyncOperations.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D9C8F741B4B259200947482 /* DRAsyncOperations.framework */; }; 27 | 7D9C8F931B4B25AC00947482 /* DRAsyncOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F901B4B25AC00947482 /* DRAsyncOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28 | 7D9C8F941B4B25AC00947482 /* DRAsyncOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F911B4B25AC00947482 /* DRAsyncOperation.m */; }; 29 | 7D9C8F951B4B25AC00947482 /* DRAsyncOperationSubclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F921B4B25AC00947482 /* DRAsyncOperationSubclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30 | 7D9C8F981B4B25BF00947482 /* DRAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F961B4B25BF00947482 /* DRAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 31 | 7D9C8F991B4B25BF00947482 /* DRAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F971B4B25BF00947482 /* DRAsyncBlockOperation.m */; }; 32 | 7D9C8F9D1B4B25D800947482 /* DRAsyncBlockOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F9B1B4B25D800947482 /* DRAsyncBlockOperationTests.m */; }; 33 | 7D9C8F9E1B4B25D800947482 /* DRAsyncOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F9C1B4B25D800947482 /* DRAsyncOperationTests.swift */; }; 34 | 7D9C8FAF1B4B277500947482 /* DRAsyncOperations.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D9C8FA41B4B277500947482 /* DRAsyncOperations.framework */; }; 35 | 7D9C8FBD1B4B27F700947482 /* DRAsyncOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F791B4B259200947482 /* DRAsyncOperations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 36 | 7D9C8FBE1B4B27FE00947482 /* DRAsyncOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F901B4B25AC00947482 /* DRAsyncOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37 | 7D9C8FBF1B4B280400947482 /* DRAsyncOperationSubclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F921B4B25AC00947482 /* DRAsyncOperationSubclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; 38 | 7D9C8FC01B4B280A00947482 /* DRAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9C8F961B4B25BF00947482 /* DRAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 39 | 7D9C8FC11B4B281400947482 /* DRAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F971B4B25BF00947482 /* DRAsyncBlockOperation.m */; }; 40 | 7D9C8FC21B4B281700947482 /* DRAsyncOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F911B4B25AC00947482 /* DRAsyncOperation.m */; }; 41 | 7D9C8FC31B4B28C800947482 /* DRAsyncBlockOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F9B1B4B25D800947482 /* DRAsyncBlockOperationTests.m */; }; 42 | 7D9C8FC41B4B28CB00947482 /* DRAsyncOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D9C8F9C1B4B25D800947482 /* DRAsyncOperationTests.swift */; }; 43 | /* End PBXBuildFile section */ 44 | 45 | /* Begin PBXContainerItemProxy section */ 46 | 7D85D6CF1C48377200548F21 /* PBXContainerItemProxy */ = { 47 | isa = PBXContainerItemProxy; 48 | containerPortal = 7D9C8F6B1B4B259200947482 /* Project object */; 49 | proxyType = 1; 50 | remoteGlobalIDString = 7D85D6C31C48377200548F21; 51 | remoteInfo = "DRAsyncOperations tvOS"; 52 | }; 53 | 7D9C8F811B4B259200947482 /* PBXContainerItemProxy */ = { 54 | isa = PBXContainerItemProxy; 55 | containerPortal = 7D9C8F6B1B4B259200947482 /* Project object */; 56 | proxyType = 1; 57 | remoteGlobalIDString = 7D9C8F731B4B259200947482; 58 | remoteInfo = DRAsyncOperations; 59 | }; 60 | 7D9C8FB01B4B277500947482 /* PBXContainerItemProxy */ = { 61 | isa = PBXContainerItemProxy; 62 | containerPortal = 7D9C8F6B1B4B259200947482 /* Project object */; 63 | proxyType = 1; 64 | remoteGlobalIDString = 7D9C8FA31B4B277500947482; 65 | remoteInfo = "DRAsyncOperations-Mac"; 66 | }; 67 | /* End PBXContainerItemProxy section */ 68 | 69 | /* Begin PBXFileReference section */ 70 | 7D85D6C41C48377200548F21 /* DRAsyncOperations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DRAsyncOperations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | 7D85D6CD1C48377200548F21 /* DRAsyncOperations tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DRAsyncOperations tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 72 | 7D85D6E01C48378900548F21 /* DRAsyncOperations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DRAsyncOperations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 73 | 7D9C8F741B4B259200947482 /* DRAsyncOperations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DRAsyncOperations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 74 | 7D9C8F781B4B259200947482 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | 7D9C8F791B4B259200947482 /* DRAsyncOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DRAsyncOperations.h; sourceTree = ""; }; 76 | 7D9C8F7F1B4B259200947482 /* DRAsyncOperations iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DRAsyncOperations iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 77 | 7D9C8F851B4B259200947482 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | 7D9C8F901B4B25AC00947482 /* DRAsyncOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRAsyncOperation.h; sourceTree = ""; }; 79 | 7D9C8F911B4B25AC00947482 /* DRAsyncOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRAsyncOperation.m; sourceTree = ""; }; 80 | 7D9C8F921B4B25AC00947482 /* DRAsyncOperationSubclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRAsyncOperationSubclass.h; sourceTree = ""; }; 81 | 7D9C8F961B4B25BF00947482 /* DRAsyncBlockOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRAsyncBlockOperation.h; sourceTree = ""; }; 82 | 7D9C8F971B4B25BF00947482 /* DRAsyncBlockOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRAsyncBlockOperation.m; sourceTree = ""; }; 83 | 7D9C8F9A1B4B25D700947482 /* DRAsyncOperationsTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DRAsyncOperationsTests-Bridging-Header.h"; sourceTree = ""; }; 84 | 7D9C8F9B1B4B25D800947482 /* DRAsyncBlockOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRAsyncBlockOperationTests.m; sourceTree = ""; }; 85 | 7D9C8F9C1B4B25D800947482 /* DRAsyncOperationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DRAsyncOperationTests.swift; sourceTree = ""; }; 86 | 7D9C8FA41B4B277500947482 /* DRAsyncOperations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DRAsyncOperations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 87 | 7D9C8FAE1B4B277500947482 /* DRAsyncOperations MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DRAsyncOperations MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 88 | /* End PBXFileReference section */ 89 | 90 | /* Begin PBXFrameworksBuildPhase section */ 91 | 7D85D6C01C48377200548F21 /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | 7D85D6CA1C48377200548F21 /* Frameworks */ = { 99 | isa = PBXFrameworksBuildPhase; 100 | buildActionMask = 2147483647; 101 | files = ( 102 | 7D85D6CE1C48377200548F21 /* DRAsyncOperations.framework in Frameworks */, 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | 7D85D6DC1C48378900548F21 /* Frameworks */ = { 107 | isa = PBXFrameworksBuildPhase; 108 | buildActionMask = 2147483647; 109 | files = ( 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | 7D9C8F701B4B259200947482 /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | 7D9C8F7C1B4B259200947482 /* Frameworks */ = { 121 | isa = PBXFrameworksBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | 7D9C8F801B4B259200947482 /* DRAsyncOperations.framework in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | 7D9C8FA01B4B277500947482 /* Frameworks */ = { 129 | isa = PBXFrameworksBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | 7D9C8FAB1B4B277500947482 /* Frameworks */ = { 136 | isa = PBXFrameworksBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | 7D9C8FAF1B4B277500947482 /* DRAsyncOperations.framework in Frameworks */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXFrameworksBuildPhase section */ 144 | 145 | /* Begin PBXGroup section */ 146 | 7D9C8F6A1B4B259200947482 = { 147 | isa = PBXGroup; 148 | children = ( 149 | 7D9C8F761B4B259200947482 /* DRAsyncOperations */, 150 | 7D9C8F831B4B259200947482 /* DRAsyncOperationsTests */, 151 | 7D9C8F751B4B259200947482 /* Products */, 152 | ); 153 | sourceTree = ""; 154 | }; 155 | 7D9C8F751B4B259200947482 /* Products */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 7D9C8F741B4B259200947482 /* DRAsyncOperations.framework */, 159 | 7D9C8F7F1B4B259200947482 /* DRAsyncOperations iOSTests.xctest */, 160 | 7D9C8FA41B4B277500947482 /* DRAsyncOperations.framework */, 161 | 7D9C8FAE1B4B277500947482 /* DRAsyncOperations MacTests.xctest */, 162 | 7D85D6C41C48377200548F21 /* DRAsyncOperations.framework */, 163 | 7D85D6CD1C48377200548F21 /* DRAsyncOperations tvOSTests.xctest */, 164 | 7D85D6E01C48378900548F21 /* DRAsyncOperations.framework */, 165 | ); 166 | name = Products; 167 | sourceTree = ""; 168 | }; 169 | 7D9C8F761B4B259200947482 /* DRAsyncOperations */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 7D9C8F791B4B259200947482 /* DRAsyncOperations.h */, 173 | 7D9C8F901B4B25AC00947482 /* DRAsyncOperation.h */, 174 | 7D9C8F911B4B25AC00947482 /* DRAsyncOperation.m */, 175 | 7D9C8F921B4B25AC00947482 /* DRAsyncOperationSubclass.h */, 176 | 7D9C8F961B4B25BF00947482 /* DRAsyncBlockOperation.h */, 177 | 7D9C8F971B4B25BF00947482 /* DRAsyncBlockOperation.m */, 178 | 7D9C8F771B4B259200947482 /* Supporting Files */, 179 | ); 180 | path = DRAsyncOperations; 181 | sourceTree = ""; 182 | }; 183 | 7D9C8F771B4B259200947482 /* Supporting Files */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 7D9C8F781B4B259200947482 /* Info.plist */, 187 | ); 188 | path = "Supporting Files"; 189 | sourceTree = ""; 190 | }; 191 | 7D9C8F831B4B259200947482 /* DRAsyncOperationsTests */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 7D9C8F9B1B4B25D800947482 /* DRAsyncBlockOperationTests.m */, 195 | 7D9C8F9C1B4B25D800947482 /* DRAsyncOperationTests.swift */, 196 | 7D9C8F841B4B259200947482 /* Supporting Files */, 197 | ); 198 | path = DRAsyncOperationsTests; 199 | sourceTree = ""; 200 | }; 201 | 7D9C8F841B4B259200947482 /* Supporting Files */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 7D9C8F9A1B4B25D700947482 /* DRAsyncOperationsTests-Bridging-Header.h */, 205 | 7D9C8F851B4B259200947482 /* Info.plist */, 206 | ); 207 | path = "Supporting Files"; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXGroup section */ 211 | 212 | /* Begin PBXHeadersBuildPhase section */ 213 | 7D85D6C11C48377200548F21 /* Headers */ = { 214 | isa = PBXHeadersBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 7D85D6F31C48388B00548F21 /* DRAsyncOperation.h in Headers */, 218 | 7D85D6F51C48389100548F21 /* DRAsyncOperations.h in Headers */, 219 | 7D85D6EF1C48387C00548F21 /* DRAsyncOperationSubclass.h in Headers */, 220 | 7D85D6F11C48388700548F21 /* DRAsyncBlockOperation.h in Headers */, 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | 7D85D6DD1C48378900548F21 /* Headers */ = { 225 | isa = PBXHeadersBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 7D85D6F41C48388C00548F21 /* DRAsyncOperation.h in Headers */, 229 | 7D85D6F61C48389100548F21 /* DRAsyncOperations.h in Headers */, 230 | 7D85D6F01C48388300548F21 /* DRAsyncOperationSubclass.h in Headers */, 231 | 7D85D6F21C48388800548F21 /* DRAsyncBlockOperation.h in Headers */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | 7D9C8F711B4B259200947482 /* Headers */ = { 236 | isa = PBXHeadersBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | 7D9C8F7A1B4B259200947482 /* DRAsyncOperations.h in Headers */, 240 | 7D9C8F981B4B25BF00947482 /* DRAsyncBlockOperation.h in Headers */, 241 | 7D9C8F951B4B25AC00947482 /* DRAsyncOperationSubclass.h in Headers */, 242 | 7D9C8F931B4B25AC00947482 /* DRAsyncOperation.h in Headers */, 243 | ); 244 | runOnlyForDeploymentPostprocessing = 0; 245 | }; 246 | 7D9C8FA11B4B277500947482 /* Headers */ = { 247 | isa = PBXHeadersBuildPhase; 248 | buildActionMask = 2147483647; 249 | files = ( 250 | 7D9C8FBE1B4B27FE00947482 /* DRAsyncOperation.h in Headers */, 251 | 7D9C8FBF1B4B280400947482 /* DRAsyncOperationSubclass.h in Headers */, 252 | 7D9C8FBD1B4B27F700947482 /* DRAsyncOperations.h in Headers */, 253 | 7D9C8FC01B4B280A00947482 /* DRAsyncBlockOperation.h in Headers */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXHeadersBuildPhase section */ 258 | 259 | /* Begin PBXNativeTarget section */ 260 | 7D85D6C31C48377200548F21 /* DRAsyncOperations tvOS */ = { 261 | isa = PBXNativeTarget; 262 | buildConfigurationList = 7D85D6D51C48377200548F21 /* Build configuration list for PBXNativeTarget "DRAsyncOperations tvOS" */; 263 | buildPhases = ( 264 | 7D85D6BF1C48377200548F21 /* Sources */, 265 | 7D85D6C01C48377200548F21 /* Frameworks */, 266 | 7D85D6C11C48377200548F21 /* Headers */, 267 | 7D85D6C21C48377200548F21 /* Resources */, 268 | ); 269 | buildRules = ( 270 | ); 271 | dependencies = ( 272 | ); 273 | name = "DRAsyncOperations tvOS"; 274 | productName = "DRAsyncOperations tvOS"; 275 | productReference = 7D85D6C41C48377200548F21 /* DRAsyncOperations.framework */; 276 | productType = "com.apple.product-type.framework"; 277 | }; 278 | 7D85D6CC1C48377200548F21 /* DRAsyncOperations tvOSTests */ = { 279 | isa = PBXNativeTarget; 280 | buildConfigurationList = 7D85D6D81C48377200548F21 /* Build configuration list for PBXNativeTarget "DRAsyncOperations tvOSTests" */; 281 | buildPhases = ( 282 | 7D85D6C91C48377200548F21 /* Sources */, 283 | 7D85D6CA1C48377200548F21 /* Frameworks */, 284 | 7D85D6CB1C48377200548F21 /* Resources */, 285 | ); 286 | buildRules = ( 287 | ); 288 | dependencies = ( 289 | 7D85D6D01C48377200548F21 /* PBXTargetDependency */, 290 | ); 291 | name = "DRAsyncOperations tvOSTests"; 292 | productName = "DRAsyncOperations tvOSTests"; 293 | productReference = 7D85D6CD1C48377200548F21 /* DRAsyncOperations tvOSTests.xctest */; 294 | productType = "com.apple.product-type.bundle.unit-test"; 295 | }; 296 | 7D85D6DF1C48378900548F21 /* DRAsyncOperations watchOS */ = { 297 | isa = PBXNativeTarget; 298 | buildConfigurationList = 7D85D6E51C48378900548F21 /* Build configuration list for PBXNativeTarget "DRAsyncOperations watchOS" */; 299 | buildPhases = ( 300 | 7D85D6DB1C48378900548F21 /* Sources */, 301 | 7D85D6DC1C48378900548F21 /* Frameworks */, 302 | 7D85D6DD1C48378900548F21 /* Headers */, 303 | 7D85D6DE1C48378900548F21 /* Resources */, 304 | ); 305 | buildRules = ( 306 | ); 307 | dependencies = ( 308 | ); 309 | name = "DRAsyncOperations watchOS"; 310 | productName = "DRAsyncOperations watchOS"; 311 | productReference = 7D85D6E01C48378900548F21 /* DRAsyncOperations.framework */; 312 | productType = "com.apple.product-type.framework"; 313 | }; 314 | 7D9C8F731B4B259200947482 /* DRAsyncOperations iOS */ = { 315 | isa = PBXNativeTarget; 316 | buildConfigurationList = 7D9C8F8A1B4B259200947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations iOS" */; 317 | buildPhases = ( 318 | 7D9C8F6F1B4B259200947482 /* Sources */, 319 | 7D9C8F701B4B259200947482 /* Frameworks */, 320 | 7D9C8F711B4B259200947482 /* Headers */, 321 | 7D9C8F721B4B259200947482 /* Resources */, 322 | ); 323 | buildRules = ( 324 | ); 325 | dependencies = ( 326 | ); 327 | name = "DRAsyncOperations iOS"; 328 | productName = DRAsyncOperations; 329 | productReference = 7D9C8F741B4B259200947482 /* DRAsyncOperations.framework */; 330 | productType = "com.apple.product-type.framework"; 331 | }; 332 | 7D9C8F7E1B4B259200947482 /* DRAsyncOperations iOSTests */ = { 333 | isa = PBXNativeTarget; 334 | buildConfigurationList = 7D9C8F8D1B4B259200947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations iOSTests" */; 335 | buildPhases = ( 336 | 7D9C8F7B1B4B259200947482 /* Sources */, 337 | 7D9C8F7C1B4B259200947482 /* Frameworks */, 338 | 7D9C8F7D1B4B259200947482 /* Resources */, 339 | ); 340 | buildRules = ( 341 | ); 342 | dependencies = ( 343 | 7D9C8F821B4B259200947482 /* PBXTargetDependency */, 344 | ); 345 | name = "DRAsyncOperations iOSTests"; 346 | productName = DRAsyncOperationsTests; 347 | productReference = 7D9C8F7F1B4B259200947482 /* DRAsyncOperations iOSTests.xctest */; 348 | productType = "com.apple.product-type.bundle.unit-test"; 349 | }; 350 | 7D9C8FA31B4B277500947482 /* DRAsyncOperations Mac */ = { 351 | isa = PBXNativeTarget; 352 | buildConfigurationList = 7D9C8FB71B4B277500947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations Mac" */; 353 | buildPhases = ( 354 | 7D9C8F9F1B4B277500947482 /* Sources */, 355 | 7D9C8FA01B4B277500947482 /* Frameworks */, 356 | 7D9C8FA11B4B277500947482 /* Headers */, 357 | 7D9C8FA21B4B277500947482 /* Resources */, 358 | ); 359 | buildRules = ( 360 | ); 361 | dependencies = ( 362 | ); 363 | name = "DRAsyncOperations Mac"; 364 | productName = "DRAsyncOperations-Mac"; 365 | productReference = 7D9C8FA41B4B277500947482 /* DRAsyncOperations.framework */; 366 | productType = "com.apple.product-type.framework"; 367 | }; 368 | 7D9C8FAD1B4B277500947482 /* DRAsyncOperations MacTests */ = { 369 | isa = PBXNativeTarget; 370 | buildConfigurationList = 7D9C8FBA1B4B277500947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations MacTests" */; 371 | buildPhases = ( 372 | 7D9C8FAA1B4B277500947482 /* Sources */, 373 | 7D9C8FAB1B4B277500947482 /* Frameworks */, 374 | 7D9C8FAC1B4B277500947482 /* Resources */, 375 | ); 376 | buildRules = ( 377 | ); 378 | dependencies = ( 379 | 7D9C8FB11B4B277500947482 /* PBXTargetDependency */, 380 | ); 381 | name = "DRAsyncOperations MacTests"; 382 | productName = "DRAsyncOperations-MacTests"; 383 | productReference = 7D9C8FAE1B4B277500947482 /* DRAsyncOperations MacTests.xctest */; 384 | productType = "com.apple.product-type.bundle.unit-test"; 385 | }; 386 | /* End PBXNativeTarget section */ 387 | 388 | /* Begin PBXProject section */ 389 | 7D9C8F6B1B4B259200947482 /* Project object */ = { 390 | isa = PBXProject; 391 | attributes = { 392 | LastSwiftUpdateCheck = 0720; 393 | LastUpgradeCheck = 0640; 394 | ORGANIZATIONNAME = "David Rodrigues"; 395 | TargetAttributes = { 396 | 7D85D6C31C48377200548F21 = { 397 | CreatedOnToolsVersion = 7.2; 398 | }; 399 | 7D85D6CC1C48377200548F21 = { 400 | CreatedOnToolsVersion = 7.2; 401 | }; 402 | 7D85D6DF1C48378900548F21 = { 403 | CreatedOnToolsVersion = 7.2; 404 | }; 405 | 7D9C8F731B4B259200947482 = { 406 | CreatedOnToolsVersion = 6.4; 407 | }; 408 | 7D9C8F7E1B4B259200947482 = { 409 | CreatedOnToolsVersion = 6.4; 410 | }; 411 | 7D9C8FA31B4B277500947482 = { 412 | CreatedOnToolsVersion = 6.4; 413 | }; 414 | 7D9C8FAD1B4B277500947482 = { 415 | CreatedOnToolsVersion = 6.4; 416 | }; 417 | }; 418 | }; 419 | buildConfigurationList = 7D9C8F6E1B4B259200947482 /* Build configuration list for PBXProject "DRAsyncOperations" */; 420 | compatibilityVersion = "Xcode 3.2"; 421 | developmentRegion = English; 422 | hasScannedForEncodings = 0; 423 | knownRegions = ( 424 | en, 425 | ); 426 | mainGroup = 7D9C8F6A1B4B259200947482; 427 | productRefGroup = 7D9C8F751B4B259200947482 /* Products */; 428 | projectDirPath = ""; 429 | projectRoot = ""; 430 | targets = ( 431 | 7D9C8F731B4B259200947482 /* DRAsyncOperations iOS */, 432 | 7D9C8F7E1B4B259200947482 /* DRAsyncOperations iOSTests */, 433 | 7D9C8FA31B4B277500947482 /* DRAsyncOperations Mac */, 434 | 7D9C8FAD1B4B277500947482 /* DRAsyncOperations MacTests */, 435 | 7D85D6C31C48377200548F21 /* DRAsyncOperations tvOS */, 436 | 7D85D6CC1C48377200548F21 /* DRAsyncOperations tvOSTests */, 437 | 7D85D6DF1C48378900548F21 /* DRAsyncOperations watchOS */, 438 | ); 439 | }; 440 | /* End PBXProject section */ 441 | 442 | /* Begin PBXResourcesBuildPhase section */ 443 | 7D85D6C21C48377200548F21 /* Resources */ = { 444 | isa = PBXResourcesBuildPhase; 445 | buildActionMask = 2147483647; 446 | files = ( 447 | ); 448 | runOnlyForDeploymentPostprocessing = 0; 449 | }; 450 | 7D85D6CB1C48377200548F21 /* Resources */ = { 451 | isa = PBXResourcesBuildPhase; 452 | buildActionMask = 2147483647; 453 | files = ( 454 | ); 455 | runOnlyForDeploymentPostprocessing = 0; 456 | }; 457 | 7D85D6DE1C48378900548F21 /* Resources */ = { 458 | isa = PBXResourcesBuildPhase; 459 | buildActionMask = 2147483647; 460 | files = ( 461 | ); 462 | runOnlyForDeploymentPostprocessing = 0; 463 | }; 464 | 7D9C8F721B4B259200947482 /* Resources */ = { 465 | isa = PBXResourcesBuildPhase; 466 | buildActionMask = 2147483647; 467 | files = ( 468 | ); 469 | runOnlyForDeploymentPostprocessing = 0; 470 | }; 471 | 7D9C8F7D1B4B259200947482 /* Resources */ = { 472 | isa = PBXResourcesBuildPhase; 473 | buildActionMask = 2147483647; 474 | files = ( 475 | ); 476 | runOnlyForDeploymentPostprocessing = 0; 477 | }; 478 | 7D9C8FA21B4B277500947482 /* Resources */ = { 479 | isa = PBXResourcesBuildPhase; 480 | buildActionMask = 2147483647; 481 | files = ( 482 | ); 483 | runOnlyForDeploymentPostprocessing = 0; 484 | }; 485 | 7D9C8FAC1B4B277500947482 /* Resources */ = { 486 | isa = PBXResourcesBuildPhase; 487 | buildActionMask = 2147483647; 488 | files = ( 489 | ); 490 | runOnlyForDeploymentPostprocessing = 0; 491 | }; 492 | /* End PBXResourcesBuildPhase section */ 493 | 494 | /* Begin PBXSourcesBuildPhase section */ 495 | 7D85D6BF1C48377200548F21 /* Sources */ = { 496 | isa = PBXSourcesBuildPhase; 497 | buildActionMask = 2147483647; 498 | files = ( 499 | 7D85D6EB1C48386900548F21 /* DRAsyncOperation.m in Sources */, 500 | 7D85D6EE1C48386900548F21 /* DRAsyncBlockOperation.m in Sources */, 501 | ); 502 | runOnlyForDeploymentPostprocessing = 0; 503 | }; 504 | 7D85D6C91C48377200548F21 /* Sources */ = { 505 | isa = PBXSourcesBuildPhase; 506 | buildActionMask = 2147483647; 507 | files = ( 508 | 7D85D6E81C48381A00548F21 /* DRAsyncBlockOperationTests.m in Sources */, 509 | 7D85D6E91C48381A00548F21 /* DRAsyncOperationTests.swift in Sources */, 510 | ); 511 | runOnlyForDeploymentPostprocessing = 0; 512 | }; 513 | 7D85D6DB1C48378900548F21 /* Sources */ = { 514 | isa = PBXSourcesBuildPhase; 515 | buildActionMask = 2147483647; 516 | files = ( 517 | 7D85D6F71C4838B100548F21 /* DRAsyncOperation.m in Sources */, 518 | 7D85D6F81C4838B100548F21 /* DRAsyncBlockOperation.m in Sources */, 519 | ); 520 | runOnlyForDeploymentPostprocessing = 0; 521 | }; 522 | 7D9C8F6F1B4B259200947482 /* Sources */ = { 523 | isa = PBXSourcesBuildPhase; 524 | buildActionMask = 2147483647; 525 | files = ( 526 | 7D9C8F991B4B25BF00947482 /* DRAsyncBlockOperation.m in Sources */, 527 | 7D9C8F941B4B25AC00947482 /* DRAsyncOperation.m in Sources */, 528 | ); 529 | runOnlyForDeploymentPostprocessing = 0; 530 | }; 531 | 7D9C8F7B1B4B259200947482 /* Sources */ = { 532 | isa = PBXSourcesBuildPhase; 533 | buildActionMask = 2147483647; 534 | files = ( 535 | 7D9C8F9E1B4B25D800947482 /* DRAsyncOperationTests.swift in Sources */, 536 | 7D9C8F9D1B4B25D800947482 /* DRAsyncBlockOperationTests.m in Sources */, 537 | ); 538 | runOnlyForDeploymentPostprocessing = 0; 539 | }; 540 | 7D9C8F9F1B4B277500947482 /* Sources */ = { 541 | isa = PBXSourcesBuildPhase; 542 | buildActionMask = 2147483647; 543 | files = ( 544 | 7D9C8FC21B4B281700947482 /* DRAsyncOperation.m in Sources */, 545 | 7D9C8FC11B4B281400947482 /* DRAsyncBlockOperation.m in Sources */, 546 | ); 547 | runOnlyForDeploymentPostprocessing = 0; 548 | }; 549 | 7D9C8FAA1B4B277500947482 /* Sources */ = { 550 | isa = PBXSourcesBuildPhase; 551 | buildActionMask = 2147483647; 552 | files = ( 553 | 7D9C8FC41B4B28CB00947482 /* DRAsyncOperationTests.swift in Sources */, 554 | 7D9C8FC31B4B28C800947482 /* DRAsyncBlockOperationTests.m in Sources */, 555 | ); 556 | runOnlyForDeploymentPostprocessing = 0; 557 | }; 558 | /* End PBXSourcesBuildPhase section */ 559 | 560 | /* Begin PBXTargetDependency section */ 561 | 7D85D6D01C48377200548F21 /* PBXTargetDependency */ = { 562 | isa = PBXTargetDependency; 563 | target = 7D85D6C31C48377200548F21 /* DRAsyncOperations tvOS */; 564 | targetProxy = 7D85D6CF1C48377200548F21 /* PBXContainerItemProxy */; 565 | }; 566 | 7D9C8F821B4B259200947482 /* PBXTargetDependency */ = { 567 | isa = PBXTargetDependency; 568 | target = 7D9C8F731B4B259200947482 /* DRAsyncOperations iOS */; 569 | targetProxy = 7D9C8F811B4B259200947482 /* PBXContainerItemProxy */; 570 | }; 571 | 7D9C8FB11B4B277500947482 /* PBXTargetDependency */ = { 572 | isa = PBXTargetDependency; 573 | target = 7D9C8FA31B4B277500947482 /* DRAsyncOperations Mac */; 574 | targetProxy = 7D9C8FB01B4B277500947482 /* PBXContainerItemProxy */; 575 | }; 576 | /* End PBXTargetDependency section */ 577 | 578 | /* Begin XCBuildConfiguration section */ 579 | 7D85D6D61C48377200548F21 /* Debug */ = { 580 | isa = XCBuildConfiguration; 581 | buildSettings = { 582 | DEBUG_INFORMATION_FORMAT = dwarf; 583 | DEFINES_MODULE = YES; 584 | DYLIB_COMPATIBILITY_VERSION = 1; 585 | DYLIB_CURRENT_VERSION = 1; 586 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 587 | ENABLE_TESTABILITY = YES; 588 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 589 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 590 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 591 | PRODUCT_NAME = DRAsyncOperations; 592 | SDKROOT = appletvos; 593 | SKIP_INSTALL = YES; 594 | TARGETED_DEVICE_FAMILY = 3; 595 | TVOS_DEPLOYMENT_TARGET = 9.0; 596 | }; 597 | name = Debug; 598 | }; 599 | 7D85D6D71C48377200548F21 /* Release */ = { 600 | isa = XCBuildConfiguration; 601 | buildSettings = { 602 | DEFINES_MODULE = YES; 603 | DYLIB_COMPATIBILITY_VERSION = 1; 604 | DYLIB_CURRENT_VERSION = 1; 605 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 606 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 607 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 608 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 609 | PRODUCT_NAME = DRAsyncOperations; 610 | SDKROOT = appletvos; 611 | SKIP_INSTALL = YES; 612 | TARGETED_DEVICE_FAMILY = 3; 613 | TVOS_DEPLOYMENT_TARGET = 9.0; 614 | }; 615 | name = Release; 616 | }; 617 | 7D85D6D91C48377200548F21 /* Debug */ = { 618 | isa = XCBuildConfiguration; 619 | buildSettings = { 620 | DEBUG_INFORMATION_FORMAT = dwarf; 621 | ENABLE_TESTABILITY = YES; 622 | INFOPLIST_FILE = "DRAsyncOperationsTests/Supporting Files/Info.plist"; 623 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 624 | PRODUCT_NAME = "$(TARGET_NAME)"; 625 | SDKROOT = appletvos; 626 | SWIFT_OBJC_BRIDGING_HEADER = "DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h"; 627 | TVOS_DEPLOYMENT_TARGET = 9.1; 628 | }; 629 | name = Debug; 630 | }; 631 | 7D85D6DA1C48377200548F21 /* Release */ = { 632 | isa = XCBuildConfiguration; 633 | buildSettings = { 634 | INFOPLIST_FILE = "DRAsyncOperationsTests/Supporting Files/Info.plist"; 635 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 636 | PRODUCT_NAME = "$(TARGET_NAME)"; 637 | SDKROOT = appletvos; 638 | SWIFT_OBJC_BRIDGING_HEADER = "DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h"; 639 | TVOS_DEPLOYMENT_TARGET = 9.1; 640 | }; 641 | name = Release; 642 | }; 643 | 7D85D6E61C48378900548F21 /* Debug */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | APPLICATION_EXTENSION_API_ONLY = YES; 647 | DEBUG_INFORMATION_FORMAT = dwarf; 648 | DEFINES_MODULE = YES; 649 | DYLIB_COMPATIBILITY_VERSION = 1; 650 | DYLIB_CURRENT_VERSION = 1; 651 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 652 | ENABLE_TESTABILITY = YES; 653 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 654 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 655 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 656 | PRODUCT_NAME = DRAsyncOperations; 657 | SDKROOT = watchos; 658 | SKIP_INSTALL = YES; 659 | TARGETED_DEVICE_FAMILY = 4; 660 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 661 | }; 662 | name = Debug; 663 | }; 664 | 7D85D6E71C48378900548F21 /* Release */ = { 665 | isa = XCBuildConfiguration; 666 | buildSettings = { 667 | APPLICATION_EXTENSION_API_ONLY = YES; 668 | DEFINES_MODULE = YES; 669 | DYLIB_COMPATIBILITY_VERSION = 1; 670 | DYLIB_CURRENT_VERSION = 1; 671 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 672 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 673 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 674 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 675 | PRODUCT_NAME = DRAsyncOperations; 676 | SDKROOT = watchos; 677 | SKIP_INSTALL = YES; 678 | TARGETED_DEVICE_FAMILY = 4; 679 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 680 | }; 681 | name = Release; 682 | }; 683 | 7D9C8F881B4B259200947482 /* Debug */ = { 684 | isa = XCBuildConfiguration; 685 | buildSettings = { 686 | ALWAYS_SEARCH_USER_PATHS = NO; 687 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 688 | CLANG_CXX_LIBRARY = "libc++"; 689 | CLANG_ENABLE_MODULES = YES; 690 | CLANG_ENABLE_OBJC_ARC = YES; 691 | CLANG_WARN_BOOL_CONVERSION = YES; 692 | CLANG_WARN_CONSTANT_CONVERSION = YES; 693 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 694 | CLANG_WARN_EMPTY_BODY = YES; 695 | CLANG_WARN_ENUM_CONVERSION = YES; 696 | CLANG_WARN_INT_CONVERSION = YES; 697 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 698 | CLANG_WARN_UNREACHABLE_CODE = YES; 699 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 700 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 701 | COPY_PHASE_STRIP = NO; 702 | CURRENT_PROJECT_VERSION = 1; 703 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 704 | ENABLE_STRICT_OBJC_MSGSEND = YES; 705 | GCC_C_LANGUAGE_STANDARD = gnu99; 706 | GCC_DYNAMIC_NO_PIC = NO; 707 | GCC_NO_COMMON_BLOCKS = YES; 708 | GCC_OPTIMIZATION_LEVEL = 0; 709 | GCC_PREPROCESSOR_DEFINITIONS = ( 710 | "DEBUG=1", 711 | "$(inherited)", 712 | ); 713 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 714 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 715 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 716 | GCC_WARN_UNDECLARED_SELECTOR = YES; 717 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 718 | GCC_WARN_UNUSED_FUNCTION = YES; 719 | GCC_WARN_UNUSED_VARIABLE = YES; 720 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 721 | MTL_ENABLE_DEBUG_INFO = YES; 722 | ONLY_ACTIVE_ARCH = YES; 723 | SDKROOT = iphoneos; 724 | TARGETED_DEVICE_FAMILY = "1,2"; 725 | VERSIONING_SYSTEM = "apple-generic"; 726 | VERSION_INFO_PREFIX = ""; 727 | }; 728 | name = Debug; 729 | }; 730 | 7D9C8F891B4B259200947482 /* Release */ = { 731 | isa = XCBuildConfiguration; 732 | buildSettings = { 733 | ALWAYS_SEARCH_USER_PATHS = NO; 734 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 735 | CLANG_CXX_LIBRARY = "libc++"; 736 | CLANG_ENABLE_MODULES = YES; 737 | CLANG_ENABLE_OBJC_ARC = YES; 738 | CLANG_WARN_BOOL_CONVERSION = YES; 739 | CLANG_WARN_CONSTANT_CONVERSION = YES; 740 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 741 | CLANG_WARN_EMPTY_BODY = YES; 742 | CLANG_WARN_ENUM_CONVERSION = YES; 743 | CLANG_WARN_INT_CONVERSION = YES; 744 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 745 | CLANG_WARN_UNREACHABLE_CODE = YES; 746 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 747 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 748 | COPY_PHASE_STRIP = NO; 749 | CURRENT_PROJECT_VERSION = 1; 750 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 751 | ENABLE_NS_ASSERTIONS = NO; 752 | ENABLE_STRICT_OBJC_MSGSEND = YES; 753 | GCC_C_LANGUAGE_STANDARD = gnu99; 754 | GCC_NO_COMMON_BLOCKS = YES; 755 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 756 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 757 | GCC_WARN_UNDECLARED_SELECTOR = YES; 758 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 759 | GCC_WARN_UNUSED_FUNCTION = YES; 760 | GCC_WARN_UNUSED_VARIABLE = YES; 761 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 762 | MTL_ENABLE_DEBUG_INFO = NO; 763 | SDKROOT = iphoneos; 764 | TARGETED_DEVICE_FAMILY = "1,2"; 765 | VALIDATE_PRODUCT = YES; 766 | VERSIONING_SYSTEM = "apple-generic"; 767 | VERSION_INFO_PREFIX = ""; 768 | }; 769 | name = Release; 770 | }; 771 | 7D9C8F8B1B4B259200947482 /* Debug */ = { 772 | isa = XCBuildConfiguration; 773 | buildSettings = { 774 | DEFINES_MODULE = YES; 775 | DYLIB_COMPATIBILITY_VERSION = 1; 776 | DYLIB_CURRENT_VERSION = 1; 777 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 778 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 779 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 780 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 781 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 782 | PRODUCT_NAME = DRAsyncOperations; 783 | SKIP_INSTALL = YES; 784 | }; 785 | name = Debug; 786 | }; 787 | 7D9C8F8C1B4B259200947482 /* Release */ = { 788 | isa = XCBuildConfiguration; 789 | buildSettings = { 790 | DEFINES_MODULE = YES; 791 | DYLIB_COMPATIBILITY_VERSION = 1; 792 | DYLIB_CURRENT_VERSION = 1; 793 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 794 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 795 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 796 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 797 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 798 | PRODUCT_NAME = DRAsyncOperations; 799 | SKIP_INSTALL = YES; 800 | }; 801 | name = Release; 802 | }; 803 | 7D9C8F8E1B4B259200947482 /* Debug */ = { 804 | isa = XCBuildConfiguration; 805 | buildSettings = { 806 | CLANG_ENABLE_MODULES = YES; 807 | FRAMEWORK_SEARCH_PATHS = ( 808 | "$(SDKROOT)/Developer/Library/Frameworks", 809 | "$(inherited)", 810 | ); 811 | GCC_PREPROCESSOR_DEFINITIONS = ( 812 | "DEBUG=1", 813 | "$(inherited)", 814 | ); 815 | INFOPLIST_FILE = "DRAsyncOperationsTests/Supporting Files/Info.plist"; 816 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 817 | PRODUCT_NAME = "$(TARGET_NAME)"; 818 | SWIFT_OBJC_BRIDGING_HEADER = "DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h"; 819 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 820 | }; 821 | name = Debug; 822 | }; 823 | 7D9C8F8F1B4B259200947482 /* Release */ = { 824 | isa = XCBuildConfiguration; 825 | buildSettings = { 826 | CLANG_ENABLE_MODULES = YES; 827 | FRAMEWORK_SEARCH_PATHS = ( 828 | "$(SDKROOT)/Developer/Library/Frameworks", 829 | "$(inherited)", 830 | ); 831 | INFOPLIST_FILE = "DRAsyncOperationsTests/Supporting Files/Info.plist"; 832 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 833 | PRODUCT_NAME = "$(TARGET_NAME)"; 834 | SWIFT_OBJC_BRIDGING_HEADER = "DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h"; 835 | }; 836 | name = Release; 837 | }; 838 | 7D9C8FB81B4B277500947482 /* Debug */ = { 839 | isa = XCBuildConfiguration; 840 | buildSettings = { 841 | APPLICATION_EXTENSION_API_ONLY = NO; 842 | COMBINE_HIDPI_IMAGES = YES; 843 | DEBUG_INFORMATION_FORMAT = dwarf; 844 | DEFINES_MODULE = YES; 845 | DYLIB_COMPATIBILITY_VERSION = 1; 846 | DYLIB_CURRENT_VERSION = 1; 847 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 848 | FRAMEWORK_VERSION = A; 849 | GCC_PREPROCESSOR_DEFINITIONS = ( 850 | "DEBUG=1", 851 | "$(inherited)", 852 | ); 853 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 854 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 855 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 856 | MACOSX_DEPLOYMENT_TARGET = 10.9; 857 | PRODUCT_NAME = DRAsyncOperations; 858 | SDKROOT = macosx; 859 | SKIP_INSTALL = YES; 860 | }; 861 | name = Debug; 862 | }; 863 | 7D9C8FB91B4B277500947482 /* Release */ = { 864 | isa = XCBuildConfiguration; 865 | buildSettings = { 866 | APPLICATION_EXTENSION_API_ONLY = NO; 867 | COMBINE_HIDPI_IMAGES = YES; 868 | DEFINES_MODULE = YES; 869 | DYLIB_COMPATIBILITY_VERSION = 1; 870 | DYLIB_CURRENT_VERSION = 1; 871 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 872 | FRAMEWORK_VERSION = A; 873 | INFOPLIST_FILE = "DRAsyncOperations/Supporting Files/Info.plist"; 874 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 875 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 876 | MACOSX_DEPLOYMENT_TARGET = 10.9; 877 | PRODUCT_NAME = DRAsyncOperations; 878 | SDKROOT = macosx; 879 | SKIP_INSTALL = YES; 880 | }; 881 | name = Release; 882 | }; 883 | 7D9C8FBB1B4B277500947482 /* Debug */ = { 884 | isa = XCBuildConfiguration; 885 | buildSettings = { 886 | COMBINE_HIDPI_IMAGES = YES; 887 | DEBUG_INFORMATION_FORMAT = dwarf; 888 | FRAMEWORK_SEARCH_PATHS = ( 889 | "$(DEVELOPER_FRAMEWORKS_DIR)", 890 | "$(inherited)", 891 | ); 892 | GCC_PREPROCESSOR_DEFINITIONS = ( 893 | "DEBUG=1", 894 | "$(inherited)", 895 | ); 896 | INFOPLIST_FILE = "DRAsyncOperationsTests/Supporting Files/Info.plist"; 897 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 898 | MACOSX_DEPLOYMENT_TARGET = 10.10; 899 | PRODUCT_NAME = "$(TARGET_NAME)"; 900 | SDKROOT = macosx; 901 | SWIFT_OBJC_BRIDGING_HEADER = "DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h"; 902 | }; 903 | name = Debug; 904 | }; 905 | 7D9C8FBC1B4B277500947482 /* Release */ = { 906 | isa = XCBuildConfiguration; 907 | buildSettings = { 908 | COMBINE_HIDPI_IMAGES = YES; 909 | FRAMEWORK_SEARCH_PATHS = ( 910 | "$(DEVELOPER_FRAMEWORKS_DIR)", 911 | "$(inherited)", 912 | ); 913 | INFOPLIST_FILE = "DRAsyncOperationsTests/Supporting Files/Info.plist"; 914 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 915 | MACOSX_DEPLOYMENT_TARGET = 10.10; 916 | PRODUCT_NAME = "$(TARGET_NAME)"; 917 | SDKROOT = macosx; 918 | SWIFT_OBJC_BRIDGING_HEADER = "DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h"; 919 | }; 920 | name = Release; 921 | }; 922 | /* End XCBuildConfiguration section */ 923 | 924 | /* Begin XCConfigurationList section */ 925 | 7D85D6D51C48377200548F21 /* Build configuration list for PBXNativeTarget "DRAsyncOperations tvOS" */ = { 926 | isa = XCConfigurationList; 927 | buildConfigurations = ( 928 | 7D85D6D61C48377200548F21 /* Debug */, 929 | 7D85D6D71C48377200548F21 /* Release */, 930 | ); 931 | defaultConfigurationIsVisible = 0; 932 | defaultConfigurationName = Release; 933 | }; 934 | 7D85D6D81C48377200548F21 /* Build configuration list for PBXNativeTarget "DRAsyncOperations tvOSTests" */ = { 935 | isa = XCConfigurationList; 936 | buildConfigurations = ( 937 | 7D85D6D91C48377200548F21 /* Debug */, 938 | 7D85D6DA1C48377200548F21 /* Release */, 939 | ); 940 | defaultConfigurationIsVisible = 0; 941 | defaultConfigurationName = Release; 942 | }; 943 | 7D85D6E51C48378900548F21 /* Build configuration list for PBXNativeTarget "DRAsyncOperations watchOS" */ = { 944 | isa = XCConfigurationList; 945 | buildConfigurations = ( 946 | 7D85D6E61C48378900548F21 /* Debug */, 947 | 7D85D6E71C48378900548F21 /* Release */, 948 | ); 949 | defaultConfigurationIsVisible = 0; 950 | defaultConfigurationName = Release; 951 | }; 952 | 7D9C8F6E1B4B259200947482 /* Build configuration list for PBXProject "DRAsyncOperations" */ = { 953 | isa = XCConfigurationList; 954 | buildConfigurations = ( 955 | 7D9C8F881B4B259200947482 /* Debug */, 956 | 7D9C8F891B4B259200947482 /* Release */, 957 | ); 958 | defaultConfigurationIsVisible = 0; 959 | defaultConfigurationName = Release; 960 | }; 961 | 7D9C8F8A1B4B259200947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations iOS" */ = { 962 | isa = XCConfigurationList; 963 | buildConfigurations = ( 964 | 7D9C8F8B1B4B259200947482 /* Debug */, 965 | 7D9C8F8C1B4B259200947482 /* Release */, 966 | ); 967 | defaultConfigurationIsVisible = 0; 968 | defaultConfigurationName = Release; 969 | }; 970 | 7D9C8F8D1B4B259200947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations iOSTests" */ = { 971 | isa = XCConfigurationList; 972 | buildConfigurations = ( 973 | 7D9C8F8E1B4B259200947482 /* Debug */, 974 | 7D9C8F8F1B4B259200947482 /* Release */, 975 | ); 976 | defaultConfigurationIsVisible = 0; 977 | defaultConfigurationName = Release; 978 | }; 979 | 7D9C8FB71B4B277500947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations Mac" */ = { 980 | isa = XCConfigurationList; 981 | buildConfigurations = ( 982 | 7D9C8FB81B4B277500947482 /* Debug */, 983 | 7D9C8FB91B4B277500947482 /* Release */, 984 | ); 985 | defaultConfigurationIsVisible = 0; 986 | defaultConfigurationName = Release; 987 | }; 988 | 7D9C8FBA1B4B277500947482 /* Build configuration list for PBXNativeTarget "DRAsyncOperations MacTests" */ = { 989 | isa = XCConfigurationList; 990 | buildConfigurations = ( 991 | 7D9C8FBB1B4B277500947482 /* Debug */, 992 | 7D9C8FBC1B4B277500947482 /* Release */, 993 | ); 994 | defaultConfigurationIsVisible = 0; 995 | defaultConfigurationName = Release; 996 | }; 997 | /* End XCConfigurationList section */ 998 | }; 999 | rootObject = 7D9C8F6B1B4B259200947482 /* Project object */; 1000 | } 1001 | -------------------------------------------------------------------------------- /DRAsyncOperations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DRAsyncOperations.xcodeproj/xcshareddata/xcschemes/DRAsyncOperations Mac.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | 90 | 96 | 97 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /DRAsyncOperations.xcodeproj/xcshareddata/xcschemes/DRAsyncOperations iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | 90 | 96 | 97 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /DRAsyncOperations.xcodeproj/xcshareddata/xcschemes/DRAsyncOperations tvOS.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 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /DRAsyncOperations.xcodeproj/xcshareddata/xcschemes/DRAsyncOperations watchOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /DRAsyncOperations/DRAsyncBlockOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncBlockOperation.h 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 23/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import "DRAsyncOperation.h" 10 | 11 | @class DRAsyncBlockOperation; 12 | 13 | /** 14 | Block to be executed when the async task should be considered finished. 15 | */ 16 | typedef void(^DRAsyncBlockOperationFinishBlock)(void); 17 | 18 | /** 19 | Block which encapsulates the async task to be performed. The block should guarantee the execution of 20 | \c DRAsyncBlockOperationFinishBlock to mark the completion of the task and consequently finish the operation. 21 | 22 | @param finishBlock the block to execute upon completion 23 | */ 24 | typedef void(^DRAsyncBlockOperationExecutionBlock)(DRAsyncBlockOperationFinishBlock finishBlock); 25 | 26 | /** 27 | The \c DRAsyncBlockOperation class is a subclass of \c DRAsyncOperation that executes an async task encapsulated in a 28 | block. 29 | */ 30 | @interface DRAsyncBlockOperation : DRAsyncOperation 31 | 32 | /** 33 | \c -init initializer is not available, please use the designated initializer to provide an execution block. 34 | */ 35 | - (instancetype)init __attribute__((unavailable("Please use `initWithBlock:` instead"))); 36 | 37 | /** 38 | Initializes a new \c DRAsyncBlockOperation with the provided block to be executed. 39 | 40 | @param executionBlock the block which encapsulates the async task. 41 | 42 | @return the newly-initialized \c DRAsyncBlockOperation 43 | */ 44 | - (instancetype)initWithBlock:(DRAsyncBlockOperationExecutionBlock)executionBlock NS_DESIGNATED_INITIALIZER; 45 | 46 | @end 47 | 48 | @interface DRAsyncBlockOperation (DRConvenienceInitializers) 49 | 50 | /** 51 | Creates a new \c DRAsyncBlockOperation with the provided block to be executed. 52 | 53 | @param executionBlock the block which encapsulates the async task. 54 | 55 | @return the newly-initialized \c DRAsyncBlockOperation 56 | */ 57 | + (instancetype)asyncBlockOperationWithBlock:(DRAsyncBlockOperationExecutionBlock)executionBlock; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /DRAsyncOperations/DRAsyncBlockOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncBlockOperation.m 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 23/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import "DRAsyncBlockOperation.h" 10 | #import "DRAsyncOperationSubclass.h" 11 | 12 | @interface DRAsyncBlockOperation () 13 | 14 | @property(nonatomic, copy) DRAsyncBlockOperationExecutionBlock executionBlock; 15 | 16 | @end 17 | 18 | @implementation DRAsyncBlockOperation 19 | 20 | - (instancetype)initWithBlock:(DRAsyncBlockOperationExecutionBlock)executionBlock 21 | { 22 | NSParameterAssert(executionBlock); 23 | 24 | // Protection for the cases where asserts are disabled 25 | if (!executionBlock) { 26 | return nil; 27 | } 28 | 29 | if ((self = [super init])) { 30 | _executionBlock = executionBlock; 31 | } 32 | 33 | return self; 34 | } 35 | 36 | #pragma mark - 37 | #pragma mark DRAsyncOperation methods 38 | 39 | - (void)asyncTask 40 | { 41 | // Invoke execution block 42 | __weak typeof(self)weakSelf = self; 43 | self.executionBlock(^{ 44 | __strong __typeof(weakSelf)strongSelf = weakSelf; 45 | [strongSelf finish]; 46 | }); 47 | } 48 | 49 | - (void)finish 50 | { 51 | // Release the execution block after completion 52 | self.executionBlock = nil; 53 | 54 | [super finish]; 55 | } 56 | 57 | 58 | #pragma mark - 59 | #pragma mark DRAsyncOperation+DRConvenienceInitializer 60 | 61 | + (instancetype)asyncBlockOperationWithBlock:(DRAsyncBlockOperationExecutionBlock)executionBlock 62 | { 63 | return [[DRAsyncBlockOperation alloc] initWithBlock:executionBlock]; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /DRAsyncOperations/DRAsyncOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncOperation.h 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 17/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | The \c DRAsyncOperation is an abstract class to encapsulate and manage execution of an asynchronous task in a very 13 | similar way as a common \c NSOperation. Because it is abstract, this class should not be used directly but instead 14 | subclass to implement the asynchronous task. 15 | 16 | To subclass and implement an async task please refer to \c DRAsyncOperationSubclass. 17 | */ 18 | @interface DRAsyncOperation : NSOperation 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /DRAsyncOperations/DRAsyncOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncOperation.m 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 17/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import "DRAsyncOperation.h" 10 | 11 | typedef NS_ENUM(char, DRAsyncOperationState) { 12 | DRAsyncOperationStateReady, 13 | DRAsyncOperationStateExecuting, 14 | DRAsyncOperationStateFinished 15 | }; 16 | 17 | static inline NSString *DRKeyPathFromAsyncOperationState(DRAsyncOperationState state) { 18 | switch (state) { 19 | case DRAsyncOperationStateReady: return @"isReady"; 20 | case DRAsyncOperationStateExecuting: return @"isExecuting"; 21 | case DRAsyncOperationStateFinished: return @"isFinished"; 22 | } 23 | } 24 | 25 | @interface DRAsyncOperation () 26 | 27 | @property(nonatomic, assign) DRAsyncOperationState state; 28 | @property(nonatomic, strong, readonly) dispatch_queue_t dispatchQueue; 29 | 30 | @end 31 | 32 | @implementation DRAsyncOperation 33 | 34 | 35 | #pragma mark - 36 | #pragma mark - Lifecycle 37 | 38 | - (instancetype)init 39 | { 40 | self = [super init]; 41 | if (self) { 42 | NSString *identifier = [NSString stringWithFormat:@"com.dmcrodrigues.%@(%p)", NSStringFromClass(self.class), self]; 43 | 44 | _dispatchQueue = dispatch_queue_create([identifier UTF8String], DISPATCH_QUEUE_SERIAL); 45 | 46 | dispatch_queue_set_specific(_dispatchQueue, (__bridge const void *)(_dispatchQueue), 47 | (__bridge void *)(self), NULL); 48 | } 49 | return self; 50 | } 51 | 52 | #pragma mark - 53 | #pragma mark NSOperation methods 54 | 55 | #if defined(__IPHONE_OS_VERSION_MIN_ALLOWED) && __IPHONE_OS_VERSION_MIN_ALLOWED >= __IPHONE_7_0 56 | - (BOOL)isAsynchronous 57 | { 58 | return YES; 59 | } 60 | #endif 61 | 62 | #if defined(__IPHONE_OS_VERSION_MIN_ALLOWED) && __IPHONE_OS_VERSION_MIN_ALLOWED < __IPHONE_7_0 63 | - (BOOL)isConcurrent 64 | { 65 | return YES; 66 | } 67 | #endif 68 | 69 | - (BOOL)isExecuting 70 | { 71 | __block BOOL isExecuting; 72 | 73 | [self performBlockAndWait:^{ 74 | isExecuting = self.state == DRAsyncOperationStateExecuting; 75 | }]; 76 | 77 | return isExecuting; 78 | } 79 | 80 | - (BOOL)isFinished 81 | { 82 | __block BOOL isFinished; 83 | 84 | [self performBlockAndWait:^{ 85 | isFinished = self.state == DRAsyncOperationStateFinished; 86 | }]; 87 | 88 | return isFinished; 89 | } 90 | 91 | - (void)start 92 | { 93 | @autoreleasepool { 94 | 95 | if ([self isCancelled]) { 96 | [self finish]; 97 | return; 98 | } 99 | 100 | __block BOOL isExecuting = YES; 101 | 102 | [self performBlockAndWait:^{ 103 | 104 | // Ignore this call if the operation is already executing or if has finished already 105 | if (self.state != DRAsyncOperationStateReady) { 106 | isExecuting = NO; 107 | } 108 | else { 109 | // Signal the beginning of operation 110 | self.state = DRAsyncOperationStateExecuting; 111 | } 112 | }]; 113 | 114 | if (isExecuting) { 115 | // Execute async task 116 | [self asyncTask]; 117 | } 118 | } 119 | } 120 | 121 | #pragma mark - 122 | #pragma mark DRAsyncOperation methods 123 | 124 | - (void)setState:(DRAsyncOperationState)state 125 | { 126 | [self performBlockAndWait:^{ 127 | 128 | NSString *oldStateKey = DRKeyPathFromAsyncOperationState(_state); 129 | NSString *newStateKey = DRKeyPathFromAsyncOperationState(state); 130 | 131 | [self willChangeValueForKey:oldStateKey]; 132 | [self willChangeValueForKey:newStateKey]; 133 | 134 | _state = state; 135 | 136 | [self didChangeValueForKey:newStateKey]; 137 | [self didChangeValueForKey:oldStateKey]; 138 | 139 | }]; 140 | } 141 | 142 | #pragma mark Protected methods 143 | 144 | - (void)asyncTask 145 | { 146 | [self finish]; 147 | } 148 | 149 | - (void)finish 150 | { 151 | [self performBlockAndWait:^{ 152 | // Signal the completion of operation 153 | if (self.state != DRAsyncOperationStateFinished) { 154 | self.state = DRAsyncOperationStateFinished; 155 | } 156 | }]; 157 | } 158 | 159 | #pragma mark - Dispatch Queue 160 | 161 | - (void)performBlockAndWait:(dispatch_block_t)block { 162 | void *context = dispatch_get_specific((__bridge const void *)(self.dispatchQueue)); 163 | BOOL runningInDispatchQueue = context == (__bridge void *)(self); 164 | 165 | if (runningInDispatchQueue) { 166 | block(); 167 | } else { 168 | dispatch_sync(self.dispatchQueue, block); 169 | } 170 | } 171 | 172 | @end 173 | -------------------------------------------------------------------------------- /DRAsyncOperations/DRAsyncOperationSubclass.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncOperationSubclass.h 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 18/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import "DRAsyncOperation.h" 10 | 11 | /** 12 | Extensions to be used by subclasses of \c DRAsyncOperation to encapsulate the code of an async task. 13 | 14 | The code that uses \c DRAsyncOperation must never call these methods. 15 | */ 16 | @interface DRAsyncOperation (DRAsyncOperationProtected) 17 | 18 | /** 19 | Performs the receiver's asynchronous task. 20 | 21 | \b Discussion \n 22 | 23 | You must override this method to perform the desired asynchronous task but do not invoke \c super at any time. \n 24 | 25 | When the asynchronous task has completed, you must call \c -finish to mark his completion and terminate the operation. 26 | */ 27 | - (void)asyncTask; 28 | 29 | /** 30 | Marks the completion of receiver's asynchronous task. 31 | */ 32 | - (void)finish NS_REQUIRES_SUPER; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /DRAsyncOperations/DRAsyncOperations.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncOperations.h 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 06/07/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for DRAsyncOperations. 12 | FOUNDATION_EXPORT double DRAsyncOperationsVersionNumber; 13 | 14 | //! Project version string for DRAsyncOperations. 15 | FOUNDATION_EXPORT const unsigned char DRAsyncOperationsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | #import 20 | #import 21 | #import 22 | -------------------------------------------------------------------------------- /DRAsyncOperations/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.dmcrodrigues.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /DRAsyncOperationsTests/DRAsyncBlockOperationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncBlockOperationTests.m 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 26/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "DRAsyncBlockOperation.h" 13 | #import "DRAsyncOperationSubclass.h" 14 | 15 | @interface DRAsyncBlockOperationTests : XCTestCase 16 | 17 | @property(nonatomic, strong) NSOperationQueue *queue; 18 | 19 | @end 20 | 21 | @implementation DRAsyncBlockOperationTests 22 | 23 | - (void)setUp { 24 | [super setUp]; 25 | 26 | self.queue = [[NSOperationQueue alloc] init]; 27 | } 28 | 29 | - (void)testScheduleSimpleAsyncOperation { 30 | 31 | XCTestExpectation *expectation = [self expectationWithDescription:@"Async Operation Completed"]; 32 | 33 | DRAsyncBlockOperation *asyncOperation = [DRAsyncBlockOperation asyncBlockOperationWithBlock:^(DRAsyncBlockOperationFinishBlock finishBlock) { 34 | 35 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 36 | 37 | [NSThread sleepForTimeInterval:2.0]; 38 | 39 | finishBlock(); 40 | }); 41 | 42 | }]; 43 | 44 | asyncOperation.completionBlock = ^{ 45 | [expectation fulfill]; 46 | }; 47 | 48 | [self.queue addOperation:asyncOperation]; 49 | 50 | [self waitForExpectationsWithTimeout:3.0 handler:^(NSError *error) { 51 | XCTAssertNil(error); 52 | }]; 53 | } 54 | 55 | - (void)testScheduleSimpleAsyncOperationWithDependencies { 56 | 57 | XCTestExpectation *expectation = [self expectationWithDescription:@"Async Operation Completed"]; 58 | 59 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 60 | 61 | [NSThread sleepForTimeInterval:1.0]; 62 | }]; 63 | 64 | DRAsyncBlockOperation *asyncOperation = [DRAsyncBlockOperation asyncBlockOperationWithBlock:^(DRAsyncBlockOperationFinishBlock finishBlock) { 65 | 66 | XCTAssertTrue([blockOperation isFinished]); 67 | 68 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 69 | 70 | [NSThread sleepForTimeInterval:2.0]; 71 | 72 | finishBlock(); 73 | }); 74 | }]; 75 | 76 | asyncOperation.completionBlock = ^{ 77 | [expectation fulfill]; 78 | }; 79 | 80 | [asyncOperation addDependency:blockOperation]; 81 | 82 | [self.queue addOperations:@[blockOperation, asyncOperation] waitUntilFinished:NO]; 83 | 84 | [self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) { 85 | XCTAssertNil(error); 86 | }]; 87 | } 88 | 89 | - (void)testStartOperationAlreadyFinished 90 | { 91 | DRAsyncBlockOperation *asyncOperation = [DRAsyncBlockOperation asyncBlockOperationWithBlock:^(DRAsyncBlockOperationFinishBlock finishBlock) { 92 | 93 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 94 | 95 | [NSThread sleepForTimeInterval:1.0]; 96 | 97 | finishBlock(); 98 | }); 99 | }]; 100 | 101 | [asyncOperation start]; 102 | [asyncOperation waitUntilFinished]; 103 | 104 | XCTAssertTrue([asyncOperation isFinished], @"operation should be finished"); 105 | 106 | [asyncOperation start]; 107 | 108 | XCTAssertTrue([asyncOperation isFinished], @"operation should be already finished"); 109 | } 110 | 111 | - (void)testStartOperationAlreadyCancelled 112 | { 113 | DRAsyncBlockOperation *asyncOperation = [DRAsyncBlockOperation asyncBlockOperationWithBlock:^(DRAsyncBlockOperationFinishBlock finishBlock) { 114 | 115 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 116 | 117 | [NSThread sleepForTimeInterval:10.0]; 118 | 119 | finishBlock(); 120 | }); 121 | }]; 122 | 123 | [asyncOperation cancel]; 124 | 125 | XCTAssertTrue([asyncOperation isCancelled], @"operation should be cancelled"); 126 | 127 | [asyncOperation start]; 128 | 129 | XCTAssertFalse([asyncOperation isExecuting], @"operation should not be finished"); 130 | XCTAssertTrue([asyncOperation isCancelled], @"operation should be cancelled"); 131 | XCTAssertTrue([asyncOperation isFinished], @"operation should be finished"); 132 | } 133 | 134 | - (void)testCancelOfLongRunningOperation 135 | { 136 | XCTestExpectation *expectation = [self expectationWithDescription:@"Async Operation Completed"]; 137 | 138 | __block DRAsyncBlockOperation *asyncOperation = [DRAsyncBlockOperation asyncBlockOperationWithBlock:^(DRAsyncBlockOperationFinishBlock finishBlock) { 139 | 140 | [NSThread sleepForTimeInterval:10.0]; 141 | 142 | if ([asyncOperation isCancelled]) { 143 | finishBlock(); 144 | return; 145 | } 146 | 147 | [NSThread sleepForTimeInterval:10.0]; 148 | 149 | if ([asyncOperation isCancelled]) { 150 | finishBlock(); 151 | return; 152 | } 153 | 154 | [NSThread sleepForTimeInterval:10.0]; 155 | 156 | finishBlock(); 157 | }]; 158 | 159 | asyncOperation.completionBlock = ^{ 160 | [expectation fulfill]; 161 | }; 162 | 163 | [self.queue addOperation:asyncOperation]; 164 | 165 | // Cancel operation 5 seconds after start executing 166 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 167 | [asyncOperation cancel]; 168 | }); 169 | 170 | // The operation, if not cancelled, will take 30 seconds to execute. We will cancel it 5 seconds after 171 | // start and it will acknowledge cancellation after 10 seconds, finishing right after that. 172 | [self waitForExpectationsWithTimeout:12.0 handler:^(NSError *error) { 173 | XCTAssertNil(error); 174 | }]; 175 | } 176 | 177 | - (void)testAyncBlockOperationWithoutExecutionBlock { 178 | #if DEBUG 179 | XCTAssertThrows([DRAsyncBlockOperation asyncBlockOperationWithBlock:nil]); 180 | #else 181 | XCTAssertNil([DRAsyncBlockOperation asyncBlockOperationWithBlock:nil]); 182 | #endif 183 | } 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /DRAsyncOperationsTests/DRAsyncOperationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DRAsyncOperationSwiftTests.swift 3 | // DRAsyncOperations 4 | // 5 | // Created by David Rodrigues on 20/04/15. 6 | // Copyright (c) 2015 David Rodrigues. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | class DRAsyncOperationSwiftTests: XCTestCase { 13 | 14 | var queue: NSOperationQueue! 15 | 16 | override func setUp() { 17 | super.setUp() 18 | 19 | queue = NSOperationQueue() 20 | } 21 | 22 | func testSimpleAsyncBlockOperation() { 23 | 24 | let expectation = self.expectationWithDescription("DRAsyncBlockOperation completed") 25 | 26 | queue.addOperation({ 27 | 28 | let asyncOperation = DRAsyncBlockOperation { (finishBlock) -> Void in 29 | 30 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 31 | 32 | NSThread.sleepForTimeInterval(0.5) 33 | 34 | finishBlock() 35 | } 36 | } 37 | 38 | asyncOperation.completionBlock = { 39 | expectation.fulfill() 40 | } 41 | 42 | return asyncOperation; 43 | }()) 44 | 45 | self.waitForExpectationsWithTimeout(2.0, handler: { (error) -> Void in 46 | XCTAssertNil(error) 47 | }) 48 | } 49 | 50 | func testAsyncBlockOperationCancellation() { 51 | 52 | let expectation = self.expectationWithDescription("DRAsyncBlockOperation completed") 53 | 54 | var asyncOperation: DRAsyncBlockOperation! 55 | 56 | asyncOperation = DRAsyncBlockOperation { (finishBlock) -> Void in 57 | 58 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 59 | 60 | NSThread.sleepForTimeInterval(2.0) 61 | 62 | if asyncOperation.cancelled { 63 | finishBlock() 64 | return; 65 | } 66 | 67 | NSThread.sleepForTimeInterval(2.0) 68 | 69 | finishBlock() 70 | } 71 | } 72 | 73 | asyncOperation.completionBlock = { 74 | expectation.fulfill() 75 | } 76 | 77 | queue.addOperation(asyncOperation) 78 | 79 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { 80 | asyncOperation.cancel() 81 | }); 82 | 83 | self.waitForExpectationsWithTimeout(3.0, handler: { (error) -> Void in 84 | XCTAssertNil(error) 85 | }) 86 | } 87 | 88 | func testAsyncOperationSubclass() { 89 | 90 | // Implement an async operation subclass 91 | class RandomAsyncOperation: DRAsyncOperation { 92 | 93 | var completed = false 94 | 95 | private override func asyncTask() { 96 | 97 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 98 | 99 | NSThread.sleepForTimeInterval(0.5) 100 | 101 | self.completed = true 102 | 103 | self.finish() 104 | } 105 | } 106 | } 107 | 108 | let expectation = self.expectationWithDescription("DRAsyncOperation subclass completed") 109 | 110 | let operation = RandomAsyncOperation() 111 | 112 | operation.completionBlock = { 113 | expectation.fulfill() 114 | } 115 | 116 | // Note that this call will not block until the operation has finished 117 | operation.start() 118 | 119 | XCTAssertTrue(operation.executing) 120 | XCTAssertFalse(operation.finished) 121 | 122 | self.waitForExpectationsWithTimeout(2.0, handler: { (error) -> Void in 123 | XCTAssertNil(error) 124 | XCTAssertTrue(operation.completed) 125 | XCTAssertTrue(operation.finished) 126 | }) 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /DRAsyncOperationsTests/Supporting Files/DRAsyncOperationsTests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "DRAsyncOperations.h" 6 | -------------------------------------------------------------------------------- /DRAsyncOperationsTests/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.dmcrodrigues.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 David Rodrigues 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DRAsyncOperations 2 | 3 | [![Travis](https://travis-ci.org/dmcrodrigues/DRAsyncOperations.svg?style=flat)](https://travis-ci.org/dmcrodrigues/DRAsyncOperations) 4 | [![CocoaPods-Version](https://img.shields.io/cocoapods/v/DRAsyncOperations.svg?style=flat)](#) 5 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![Platform](https://img.shields.io/badge/Platform-ios%20%7C%20osx%20%7C%20watchos%20%7C%20tvos-lightgrey.svg?style=flat)](#) 7 | [![MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](#) 8 | 9 | Implementation of a concurrent `NSOperation` to abstract and help the creation of asynchronous operations. 10 | 11 | ## Motivation 12 | 13 | > We code in an asynchronous world. We promise. 14 | > 15 | > -- [PromiseKit](http://promisekit.org) 16 | 17 | Every iOS developer certainly agrees with this statement, a great part of our code is highly asynchronous and this brings a few challenges to us. Luckily, we have a few mechanisms to structure our business logic, `NSOperation` in combination with `NSOperationQueue` is one of them, it's powerful and flexible. 18 | 19 | However, despite all the flexibility, if you need to make an asynchronous call on a `NSOperation` you're doomed. Remember that a `NSOperation` will finish right after the `-main` method returns. So, you will probably end up using a semaphore or something similar to lock the operation while the async call is running otherwise it will finish before time. This doesn't feel right. 20 | 21 | Actually, you're not completely doomed, due the great flexibility offered by `NSOperation` you're able to create a concurrent operation where you can control exactly when the operation should be considered finished and with this finish the operation only after the async call have completed. 22 | 23 | Implement a concurrent operation it's not hard but there're a few things that you will need to implement in every operation of this kind. This is the main reason behind `DRAsyncOperation`, a class that implements the base functionality required to use concurrent operations and, consequently, use asynchronous code in `NSOperation`s. 24 | 25 | ## Installation 26 | 27 | ### CocoaPods 28 | 29 | ```pod 'DRAsyncOperations'``` 30 | 31 | ### Carthage 32 | 33 | ```github "dmcrodrigues/DRAsyncOperations"``` 34 | 35 | ### Manually 36 | 37 | Drag all files located in `DRAsyncOperation` folder to your project and you're done. You can also import the Xcode project into your workspace as a dependency. 38 | 39 | ## Usage 40 | 41 | Implementing an asynchronous operation using `DRAsyncOperation` is straightforward and it may seem very similar to implementing a custom `NSOperation`. 42 | 43 | 1. Subclass `DRAsyncOperation`; 44 | 2. Override the method `-asyncTask;` where you implement your asynchronous code, you can think of it as the equivalent of `-main` method from non-concurrent operations; 45 | 3. When your asynchronous code finishes, call the method `-finish` to finish the operation, this part is new comparing to `NSOperation`. 46 | 47 | > The methods referred above are available in `DRAsyncOperationSubclass.h`. 48 | 49 | ### Block API 50 | 51 | You can also create an asynchronous operation using a simple block using `DRAsyncBlockOperation` which may seem very similar to a `NSBlockOperation`. 52 | 53 | ### Start operations manually 54 | 55 | If you create an instance of `DRAsyncOperation` and then call `-start` to manually start the operation you should be aware that this call may not block until completion due the asynchronous nature of this operations. If you want the same behavior of a non-concurrent operation you should invoke `-waitUntilFinished` after `-start`. 56 | 57 | ## Examples 58 | 59 | ### Objetive-C 60 | 61 | 62 | #### 1. Encapsulate an async task in a operation 63 | 64 | ```objective-c 65 | 66 | // DRNetworkAsyncOperation.h 67 | 68 | #import "DRAsyncOperation.h" 69 | 70 | @interface DRNetworkAsyncOperation : DRAsyncOperation 71 | 72 | @end 73 | 74 | // DRNetworkAsyncOperation.m 75 | 76 | #import "DRNetworkAsyncOperation.h" 77 | #import "DRAsyncOperationSubclass.h" 78 | 79 | @implementation DRNetworkAsyncOperation 80 | 81 | - (void)asyncTask 82 | { 83 | NSURL *githubURL = [NSURL URLWithString:@"https://github.com"]; 84 | 85 | [[NSURLSession sharedSession] dataTaskWithURL:githubURL 86 | completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 87 | 88 | // Do your stuff ... 89 | 90 | // When you're done, finish the operation 91 | [self finish]; 92 | }]; 93 | } 94 | 95 | @end 96 | 97 | ``` 98 | 99 | #### 2. Encapsulate an async task in a block 100 | 101 | ```objective-c 102 | 103 | NSOperationQueue *queue; 104 | 105 | CLGeocoder *geocoder; 106 | CLLocation *location; 107 | 108 | NSOperation *asyncOperation = [DRAsyncBlockOperation asyncBlockOperationWithBlock:^(DRAsyncBlockOperationFinishBlock finish) { 109 | 110 | [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { 111 | 112 | // Do your stuff ... 113 | 114 | // When you're done, finish the operation 115 | finish(); 116 | }]; 117 | 118 | }]; 119 | 120 | [queue addOperation:asyncOperation]; 121 | 122 | ``` 123 | 124 | ## Swift 125 | 126 | Swift is supported out-of-the-box, you only need to import the relevant headers in your Bridging Header. 127 | 128 | ```objective-c 129 | 130 | // If you want to implement async tasks in operations 131 | #import "DRAsyncOperation.h" 132 | #import "DRAsyncOperationSubclass.h" 133 | 134 | // If you want to implement async tasks in blocks 135 | #import "DRAsyncBlockOperation.h" 136 | 137 | ``` 138 | 139 | The block API in Swift it's more compact in comparison with Objective-C. 140 | 141 | ```swift 142 | 143 | var queue: NSOperationQueue 144 | 145 | var geocoder: CLGeocoder 146 | var location: CLLocation 147 | 148 | var asyncOperation: DRAsyncBlockOperation! 149 | 150 | asyncOperation = DRAsyncBlockOperation { (finish) -> Void in 151 | 152 | // This is automatically checked for you at the beginning of the operation but you could check it during your execution 153 | if asyncOperation.isCancelled() { 154 | finish() 155 | return 156 | } 157 | 158 | geocoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in 159 | 160 | // Do your stuff ... 161 | 162 | // When you're done, finish the operation 163 | finish() 164 | 165 | }) 166 | } 167 | 168 | queue.addOperation(asyncOperation) 169 | 170 | ``` 171 | 172 | ## Creator 173 | 174 | [David Rodrigues](https://github.com/dmcrodrigues) 175 | [@dmcrodrigues](https://twitter.com/dmcrodrigues) 176 | 177 | ## License 178 | 179 | DRAsyncOperation is released under the [MIT License](http://www.opensource.org/licenses/MIT). 180 | --------------------------------------------------------------------------------