├── .gitignore ├── LICENSE ├── OperationQueues.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── OperationQueues ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── CustomOperation │ ├── OQConcurrentOperation.h │ ├── OQConcurrentOperation.m │ ├── OQNonConcurrentOperation.h │ └── OQNonConcurrentOperation.m ├── ExecuteOperation │ ├── OQManualExecuteOperation.h │ ├── OQManualExecuteOperation.m │ ├── OQUseOperationQueue.h │ └── OQUseOperationQueue.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── NSBlockOperation │ ├── OQCreateBlockOperation.h │ └── OQCreateBlockOperation.m ├── NSInvocationOperation │ ├── ExecuteOperation │ │ ├── OQManualExecuteOperation.h │ │ ├── OQManualExecuteOperation.m │ │ ├── OQUseOperationQueue.h │ │ └── OQUseOperationQueue.m │ ├── OQCreateInvocationOperation.h │ └── OQCreateInvocationOperation.m ├── ViewController.h ├── ViewController.m └── main.m ├── OperationQueuesTests ├── CustomOperation │ ├── OQConcurrentOperationTests.m │ └── OQNonConcurrentOperationTests.m ├── ExecuteOperation │ ├── OQManualExecuteOperationTests.m │ └── OQUseOperationQueueTests.m ├── Info.plist ├── NSBlockOperation │ └── OQCreateBlockOperationTests.m └── NSInvocationOperation │ └── OQCreateInvocationOperationTests.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 leichunfeng 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 | 23 | -------------------------------------------------------------------------------- /OperationQueues.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 249B41381B6C960B00870EFF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41371B6C960B00870EFF /* main.m */; }; 11 | 249B413B1B6C960B00870EFF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B413A1B6C960B00870EFF /* AppDelegate.m */; }; 12 | 249B413E1B6C960B00870EFF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B413D1B6C960B00870EFF /* ViewController.m */; }; 13 | 249B41411B6C960B00870EFF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 249B413F1B6C960B00870EFF /* Main.storyboard */; }; 14 | 249B41431B6C960B00870EFF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 249B41421B6C960B00870EFF /* Images.xcassets */; }; 15 | 249B41461B6C960B00870EFF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 249B41441B6C960B00870EFF /* LaunchScreen.xib */; }; 16 | 249B41661B6CA65400870EFF /* OQCreateInvocationOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41651B6CA65400870EFF /* OQCreateInvocationOperation.m */; }; 17 | 249B41691B6CA72300870EFF /* OQCreateInvocationOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41681B6CA72300870EFF /* OQCreateInvocationOperationTests.m */; }; 18 | 249B416D1B6CB85100870EFF /* OQCreateBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B416C1B6CB85100870EFF /* OQCreateBlockOperation.m */; }; 19 | 249B41701B6CB90B00870EFF /* OQCreateBlockOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B416F1B6CB90B00870EFF /* OQCreateBlockOperationTests.m */; }; 20 | 249B41741B6CCA3600870EFF /* OQNonConcurrentOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41731B6CCA3600870EFF /* OQNonConcurrentOperation.m */; }; 21 | 249B41771B6CCBDB00870EFF /* OQNonConcurrentOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41761B6CCBDB00870EFF /* OQNonConcurrentOperationTests.m */; }; 22 | 249B417A1B6CFC8200870EFF /* OQConcurrentOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41791B6CFC8200870EFF /* OQConcurrentOperation.m */; }; 23 | 249B418B1B6E5E4000870EFF /* OQConcurrentOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B418A1B6E5E4000870EFF /* OQConcurrentOperationTests.m */; }; 24 | 249B419F1B6F06C700870EFF /* OQManualExecuteOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B419C1B6F06C700870EFF /* OQManualExecuteOperation.m */; }; 25 | 249B41A01B6F06C700870EFF /* OQUseOperationQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B419E1B6F06C700870EFF /* OQUseOperationQueue.m */; }; 26 | 249B41A41B6F06EF00870EFF /* OQManualExecuteOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41A21B6F06EF00870EFF /* OQManualExecuteOperationTests.m */; }; 27 | 249B41A51B6F06EF00870EFF /* OQUseOperationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 249B41A31B6F06EF00870EFF /* OQUseOperationQueueTests.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 249B414C1B6C960B00870EFF /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 249B412A1B6C960B00870EFF /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 249B41311B6C960B00870EFF; 36 | remoteInfo = OperationQueues; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 249B41321B6C960B00870EFF /* OperationQueues.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OperationQueues.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 249B41361B6C960B00870EFF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 249B41371B6C960B00870EFF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | 249B41391B6C960B00870EFF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | 249B413A1B6C960B00870EFF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | 249B413C1B6C960B00870EFF /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 47 | 249B413D1B6C960B00870EFF /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 48 | 249B41401B6C960B00870EFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 249B41421B6C960B00870EFF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 50 | 249B41451B6C960B00870EFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 51 | 249B414B1B6C960B00870EFF /* OperationQueuesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OperationQueuesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 249B41501B6C960B00870EFF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 249B41641B6CA65400870EFF /* OQCreateInvocationOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OQCreateInvocationOperation.h; sourceTree = ""; }; 54 | 249B41651B6CA65400870EFF /* OQCreateInvocationOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQCreateInvocationOperation.m; sourceTree = ""; }; 55 | 249B41681B6CA72300870EFF /* OQCreateInvocationOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQCreateInvocationOperationTests.m; sourceTree = ""; }; 56 | 249B416B1B6CB85100870EFF /* OQCreateBlockOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OQCreateBlockOperation.h; sourceTree = ""; }; 57 | 249B416C1B6CB85100870EFF /* OQCreateBlockOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQCreateBlockOperation.m; sourceTree = ""; }; 58 | 249B416F1B6CB90B00870EFF /* OQCreateBlockOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQCreateBlockOperationTests.m; sourceTree = ""; }; 59 | 249B41721B6CCA3600870EFF /* OQNonConcurrentOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OQNonConcurrentOperation.h; sourceTree = ""; }; 60 | 249B41731B6CCA3600870EFF /* OQNonConcurrentOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQNonConcurrentOperation.m; sourceTree = ""; }; 61 | 249B41761B6CCBDB00870EFF /* OQNonConcurrentOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQNonConcurrentOperationTests.m; sourceTree = ""; }; 62 | 249B41781B6CFC8200870EFF /* OQConcurrentOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OQConcurrentOperation.h; sourceTree = ""; }; 63 | 249B41791B6CFC8200870EFF /* OQConcurrentOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQConcurrentOperation.m; sourceTree = ""; }; 64 | 249B418A1B6E5E4000870EFF /* OQConcurrentOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQConcurrentOperationTests.m; sourceTree = ""; }; 65 | 249B419B1B6F06C700870EFF /* OQManualExecuteOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OQManualExecuteOperation.h; sourceTree = ""; }; 66 | 249B419C1B6F06C700870EFF /* OQManualExecuteOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQManualExecuteOperation.m; sourceTree = ""; }; 67 | 249B419D1B6F06C700870EFF /* OQUseOperationQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OQUseOperationQueue.h; sourceTree = ""; }; 68 | 249B419E1B6F06C700870EFF /* OQUseOperationQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQUseOperationQueue.m; sourceTree = ""; }; 69 | 249B41A21B6F06EF00870EFF /* OQManualExecuteOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQManualExecuteOperationTests.m; sourceTree = ""; }; 70 | 249B41A31B6F06EF00870EFF /* OQUseOperationQueueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OQUseOperationQueueTests.m; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | 249B412F1B6C960B00870EFF /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | 249B41481B6C960B00870EFF /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | 249B41291B6C960B00870EFF = { 92 | isa = PBXGroup; 93 | children = ( 94 | 249B41341B6C960B00870EFF /* OperationQueues */, 95 | 249B414E1B6C960B00870EFF /* OperationQueuesTests */, 96 | 249B41331B6C960B00870EFF /* Products */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 249B41331B6C960B00870EFF /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 249B41321B6C960B00870EFF /* OperationQueues.app */, 104 | 249B414B1B6C960B00870EFF /* OperationQueuesTests.xctest */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | 249B41341B6C960B00870EFF /* OperationQueues */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 249B415D1B6CA2A900870EFF /* NSInvocationOperation */, 113 | 249B416A1B6CB6F000870EFF /* NSBlockOperation */, 114 | 249B41711B6CCA1800870EFF /* CustomOperation */, 115 | 249B419A1B6F06C700870EFF /* ExecuteOperation */, 116 | 249B41391B6C960B00870EFF /* AppDelegate.h */, 117 | 249B413A1B6C960B00870EFF /* AppDelegate.m */, 118 | 249B413C1B6C960B00870EFF /* ViewController.h */, 119 | 249B413D1B6C960B00870EFF /* ViewController.m */, 120 | 249B413F1B6C960B00870EFF /* Main.storyboard */, 121 | 249B41421B6C960B00870EFF /* Images.xcassets */, 122 | 249B41441B6C960B00870EFF /* LaunchScreen.xib */, 123 | 249B41351B6C960B00870EFF /* Supporting Files */, 124 | ); 125 | path = OperationQueues; 126 | sourceTree = ""; 127 | }; 128 | 249B41351B6C960B00870EFF /* Supporting Files */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 249B41361B6C960B00870EFF /* Info.plist */, 132 | 249B41371B6C960B00870EFF /* main.m */, 133 | ); 134 | name = "Supporting Files"; 135 | sourceTree = ""; 136 | }; 137 | 249B414E1B6C960B00870EFF /* OperationQueuesTests */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 249B41671B6CA71400870EFF /* NSInvocationOperation */, 141 | 249B416E1B6CB8FD00870EFF /* NSBlockOperation */, 142 | 249B41751B6CCBCE00870EFF /* CustomOperation */, 143 | 249B41A11B6F06EF00870EFF /* ExecuteOperation */, 144 | 249B414F1B6C960B00870EFF /* Supporting Files */, 145 | ); 146 | path = OperationQueuesTests; 147 | sourceTree = ""; 148 | }; 149 | 249B414F1B6C960B00870EFF /* Supporting Files */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 249B41501B6C960B00870EFF /* Info.plist */, 153 | ); 154 | name = "Supporting Files"; 155 | sourceTree = ""; 156 | }; 157 | 249B415D1B6CA2A900870EFF /* NSInvocationOperation */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 249B41641B6CA65400870EFF /* OQCreateInvocationOperation.h */, 161 | 249B41651B6CA65400870EFF /* OQCreateInvocationOperation.m */, 162 | ); 163 | path = NSInvocationOperation; 164 | sourceTree = ""; 165 | }; 166 | 249B41671B6CA71400870EFF /* NSInvocationOperation */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 249B41681B6CA72300870EFF /* OQCreateInvocationOperationTests.m */, 170 | ); 171 | path = NSInvocationOperation; 172 | sourceTree = ""; 173 | }; 174 | 249B416A1B6CB6F000870EFF /* NSBlockOperation */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 249B416B1B6CB85100870EFF /* OQCreateBlockOperation.h */, 178 | 249B416C1B6CB85100870EFF /* OQCreateBlockOperation.m */, 179 | ); 180 | path = NSBlockOperation; 181 | sourceTree = ""; 182 | }; 183 | 249B416E1B6CB8FD00870EFF /* NSBlockOperation */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 249B416F1B6CB90B00870EFF /* OQCreateBlockOperationTests.m */, 187 | ); 188 | path = NSBlockOperation; 189 | sourceTree = ""; 190 | }; 191 | 249B41711B6CCA1800870EFF /* CustomOperation */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 249B41721B6CCA3600870EFF /* OQNonConcurrentOperation.h */, 195 | 249B41731B6CCA3600870EFF /* OQNonConcurrentOperation.m */, 196 | 249B41781B6CFC8200870EFF /* OQConcurrentOperation.h */, 197 | 249B41791B6CFC8200870EFF /* OQConcurrentOperation.m */, 198 | ); 199 | path = CustomOperation; 200 | sourceTree = ""; 201 | }; 202 | 249B41751B6CCBCE00870EFF /* CustomOperation */ = { 203 | isa = PBXGroup; 204 | children = ( 205 | 249B41761B6CCBDB00870EFF /* OQNonConcurrentOperationTests.m */, 206 | 249B418A1B6E5E4000870EFF /* OQConcurrentOperationTests.m */, 207 | ); 208 | path = CustomOperation; 209 | sourceTree = ""; 210 | }; 211 | 249B419A1B6F06C700870EFF /* ExecuteOperation */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | 249B419D1B6F06C700870EFF /* OQUseOperationQueue.h */, 215 | 249B419E1B6F06C700870EFF /* OQUseOperationQueue.m */, 216 | 249B419B1B6F06C700870EFF /* OQManualExecuteOperation.h */, 217 | 249B419C1B6F06C700870EFF /* OQManualExecuteOperation.m */, 218 | ); 219 | path = ExecuteOperation; 220 | sourceTree = ""; 221 | }; 222 | 249B41A11B6F06EF00870EFF /* ExecuteOperation */ = { 223 | isa = PBXGroup; 224 | children = ( 225 | 249B41A31B6F06EF00870EFF /* OQUseOperationQueueTests.m */, 226 | 249B41A21B6F06EF00870EFF /* OQManualExecuteOperationTests.m */, 227 | ); 228 | path = ExecuteOperation; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXGroup section */ 232 | 233 | /* Begin PBXNativeTarget section */ 234 | 249B41311B6C960B00870EFF /* OperationQueues */ = { 235 | isa = PBXNativeTarget; 236 | buildConfigurationList = 249B41551B6C960B00870EFF /* Build configuration list for PBXNativeTarget "OperationQueues" */; 237 | buildPhases = ( 238 | 249B412E1B6C960B00870EFF /* Sources */, 239 | 249B412F1B6C960B00870EFF /* Frameworks */, 240 | 249B41301B6C960B00870EFF /* Resources */, 241 | ); 242 | buildRules = ( 243 | ); 244 | dependencies = ( 245 | ); 246 | name = OperationQueues; 247 | productName = OperationQueues; 248 | productReference = 249B41321B6C960B00870EFF /* OperationQueues.app */; 249 | productType = "com.apple.product-type.application"; 250 | }; 251 | 249B414A1B6C960B00870EFF /* OperationQueuesTests */ = { 252 | isa = PBXNativeTarget; 253 | buildConfigurationList = 249B41581B6C960B00870EFF /* Build configuration list for PBXNativeTarget "OperationQueuesTests" */; 254 | buildPhases = ( 255 | 249B41471B6C960B00870EFF /* Sources */, 256 | 249B41481B6C960B00870EFF /* Frameworks */, 257 | 249B41491B6C960B00870EFF /* Resources */, 258 | ); 259 | buildRules = ( 260 | ); 261 | dependencies = ( 262 | 249B414D1B6C960B00870EFF /* PBXTargetDependency */, 263 | ); 264 | name = OperationQueuesTests; 265 | productName = OperationQueuesTests; 266 | productReference = 249B414B1B6C960B00870EFF /* OperationQueuesTests.xctest */; 267 | productType = "com.apple.product-type.bundle.unit-test"; 268 | }; 269 | /* End PBXNativeTarget section */ 270 | 271 | /* Begin PBXProject section */ 272 | 249B412A1B6C960B00870EFF /* Project object */ = { 273 | isa = PBXProject; 274 | attributes = { 275 | LastUpgradeCheck = 0640; 276 | ORGANIZATIONNAME = leichunfeng; 277 | TargetAttributes = { 278 | 249B41311B6C960B00870EFF = { 279 | CreatedOnToolsVersion = 6.4; 280 | }; 281 | 249B414A1B6C960B00870EFF = { 282 | CreatedOnToolsVersion = 6.4; 283 | TestTargetID = 249B41311B6C960B00870EFF; 284 | }; 285 | }; 286 | }; 287 | buildConfigurationList = 249B412D1B6C960B00870EFF /* Build configuration list for PBXProject "OperationQueues" */; 288 | compatibilityVersion = "Xcode 3.2"; 289 | developmentRegion = English; 290 | hasScannedForEncodings = 0; 291 | knownRegions = ( 292 | en, 293 | Base, 294 | ); 295 | mainGroup = 249B41291B6C960B00870EFF; 296 | productRefGroup = 249B41331B6C960B00870EFF /* Products */; 297 | projectDirPath = ""; 298 | projectRoot = ""; 299 | targets = ( 300 | 249B41311B6C960B00870EFF /* OperationQueues */, 301 | 249B414A1B6C960B00870EFF /* OperationQueuesTests */, 302 | ); 303 | }; 304 | /* End PBXProject section */ 305 | 306 | /* Begin PBXResourcesBuildPhase section */ 307 | 249B41301B6C960B00870EFF /* Resources */ = { 308 | isa = PBXResourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | 249B41411B6C960B00870EFF /* Main.storyboard in Resources */, 312 | 249B41461B6C960B00870EFF /* LaunchScreen.xib in Resources */, 313 | 249B41431B6C960B00870EFF /* Images.xcassets in Resources */, 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | 249B41491B6C960B00870EFF /* Resources */ = { 318 | isa = PBXResourcesBuildPhase; 319 | buildActionMask = 2147483647; 320 | files = ( 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | /* End PBXResourcesBuildPhase section */ 325 | 326 | /* Begin PBXSourcesBuildPhase section */ 327 | 249B412E1B6C960B00870EFF /* Sources */ = { 328 | isa = PBXSourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | 249B41741B6CCA3600870EFF /* OQNonConcurrentOperation.m in Sources */, 332 | 249B41A01B6F06C700870EFF /* OQUseOperationQueue.m in Sources */, 333 | 249B413E1B6C960B00870EFF /* ViewController.m in Sources */, 334 | 249B416D1B6CB85100870EFF /* OQCreateBlockOperation.m in Sources */, 335 | 249B413B1B6C960B00870EFF /* AppDelegate.m in Sources */, 336 | 249B41381B6C960B00870EFF /* main.m in Sources */, 337 | 249B417A1B6CFC8200870EFF /* OQConcurrentOperation.m in Sources */, 338 | 249B41661B6CA65400870EFF /* OQCreateInvocationOperation.m in Sources */, 339 | 249B419F1B6F06C700870EFF /* OQManualExecuteOperation.m in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | 249B41471B6C960B00870EFF /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | 249B41691B6CA72300870EFF /* OQCreateInvocationOperationTests.m in Sources */, 348 | 249B41771B6CCBDB00870EFF /* OQNonConcurrentOperationTests.m in Sources */, 349 | 249B41A41B6F06EF00870EFF /* OQManualExecuteOperationTests.m in Sources */, 350 | 249B418B1B6E5E4000870EFF /* OQConcurrentOperationTests.m in Sources */, 351 | 249B41701B6CB90B00870EFF /* OQCreateBlockOperationTests.m in Sources */, 352 | 249B41A51B6F06EF00870EFF /* OQUseOperationQueueTests.m in Sources */, 353 | ); 354 | runOnlyForDeploymentPostprocessing = 0; 355 | }; 356 | /* End PBXSourcesBuildPhase section */ 357 | 358 | /* Begin PBXTargetDependency section */ 359 | 249B414D1B6C960B00870EFF /* PBXTargetDependency */ = { 360 | isa = PBXTargetDependency; 361 | target = 249B41311B6C960B00870EFF /* OperationQueues */; 362 | targetProxy = 249B414C1B6C960B00870EFF /* PBXContainerItemProxy */; 363 | }; 364 | /* End PBXTargetDependency section */ 365 | 366 | /* Begin PBXVariantGroup section */ 367 | 249B413F1B6C960B00870EFF /* Main.storyboard */ = { 368 | isa = PBXVariantGroup; 369 | children = ( 370 | 249B41401B6C960B00870EFF /* Base */, 371 | ); 372 | name = Main.storyboard; 373 | sourceTree = ""; 374 | }; 375 | 249B41441B6C960B00870EFF /* LaunchScreen.xib */ = { 376 | isa = PBXVariantGroup; 377 | children = ( 378 | 249B41451B6C960B00870EFF /* Base */, 379 | ); 380 | name = LaunchScreen.xib; 381 | sourceTree = ""; 382 | }; 383 | /* End PBXVariantGroup section */ 384 | 385 | /* Begin XCBuildConfiguration section */ 386 | 249B41531B6C960B00870EFF /* Debug */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | ALWAYS_SEARCH_USER_PATHS = NO; 390 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 391 | CLANG_CXX_LIBRARY = "libc++"; 392 | CLANG_ENABLE_MODULES = YES; 393 | CLANG_ENABLE_OBJC_ARC = YES; 394 | CLANG_WARN_BOOL_CONVERSION = YES; 395 | CLANG_WARN_CONSTANT_CONVERSION = YES; 396 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 397 | CLANG_WARN_EMPTY_BODY = YES; 398 | CLANG_WARN_ENUM_CONVERSION = YES; 399 | CLANG_WARN_INT_CONVERSION = YES; 400 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 401 | CLANG_WARN_UNREACHABLE_CODE = YES; 402 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 403 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 404 | COPY_PHASE_STRIP = NO; 405 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 406 | ENABLE_STRICT_OBJC_MSGSEND = YES; 407 | GCC_C_LANGUAGE_STANDARD = gnu99; 408 | GCC_DYNAMIC_NO_PIC = NO; 409 | GCC_NO_COMMON_BLOCKS = YES; 410 | GCC_OPTIMIZATION_LEVEL = 0; 411 | GCC_PREPROCESSOR_DEFINITIONS = ( 412 | "DEBUG=1", 413 | "$(inherited)", 414 | ); 415 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 418 | GCC_WARN_UNDECLARED_SELECTOR = YES; 419 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 420 | GCC_WARN_UNUSED_FUNCTION = YES; 421 | GCC_WARN_UNUSED_VARIABLE = YES; 422 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 423 | MTL_ENABLE_DEBUG_INFO = YES; 424 | ONLY_ACTIVE_ARCH = YES; 425 | SDKROOT = iphoneos; 426 | }; 427 | name = Debug; 428 | }; 429 | 249B41541B6C960B00870EFF /* Release */ = { 430 | isa = XCBuildConfiguration; 431 | buildSettings = { 432 | ALWAYS_SEARCH_USER_PATHS = NO; 433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 434 | CLANG_CXX_LIBRARY = "libc++"; 435 | CLANG_ENABLE_MODULES = YES; 436 | CLANG_ENABLE_OBJC_ARC = YES; 437 | CLANG_WARN_BOOL_CONVERSION = YES; 438 | CLANG_WARN_CONSTANT_CONVERSION = YES; 439 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 440 | CLANG_WARN_EMPTY_BODY = YES; 441 | CLANG_WARN_ENUM_CONVERSION = YES; 442 | CLANG_WARN_INT_CONVERSION = YES; 443 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 444 | CLANG_WARN_UNREACHABLE_CODE = YES; 445 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 446 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 447 | COPY_PHASE_STRIP = NO; 448 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 449 | ENABLE_NS_ASSERTIONS = NO; 450 | ENABLE_STRICT_OBJC_MSGSEND = YES; 451 | GCC_C_LANGUAGE_STANDARD = gnu99; 452 | GCC_NO_COMMON_BLOCKS = YES; 453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 455 | GCC_WARN_UNDECLARED_SELECTOR = YES; 456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 457 | GCC_WARN_UNUSED_FUNCTION = YES; 458 | GCC_WARN_UNUSED_VARIABLE = YES; 459 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 460 | MTL_ENABLE_DEBUG_INFO = NO; 461 | SDKROOT = iphoneos; 462 | VALIDATE_PRODUCT = YES; 463 | }; 464 | name = Release; 465 | }; 466 | 249B41561B6C960B00870EFF /* Debug */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 470 | GCC_PREFIX_HEADER = ""; 471 | INFOPLIST_FILE = OperationQueues/Info.plist; 472 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | }; 475 | name = Debug; 476 | }; 477 | 249B41571B6C960B00870EFF /* Release */ = { 478 | isa = XCBuildConfiguration; 479 | buildSettings = { 480 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 481 | GCC_PREFIX_HEADER = ""; 482 | INFOPLIST_FILE = OperationQueues/Info.plist; 483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 484 | PRODUCT_NAME = "$(TARGET_NAME)"; 485 | }; 486 | name = Release; 487 | }; 488 | 249B41591B6C960B00870EFF /* Debug */ = { 489 | isa = XCBuildConfiguration; 490 | buildSettings = { 491 | BUNDLE_LOADER = "$(TEST_HOST)"; 492 | FRAMEWORK_SEARCH_PATHS = ( 493 | "$(SDKROOT)/Developer/Library/Frameworks", 494 | "$(inherited)", 495 | ); 496 | GCC_PREPROCESSOR_DEFINITIONS = ( 497 | "DEBUG=1", 498 | "$(inherited)", 499 | ); 500 | INFOPLIST_FILE = OperationQueuesTests/Info.plist; 501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OperationQueues.app/OperationQueues"; 504 | }; 505 | name = Debug; 506 | }; 507 | 249B415A1B6C960B00870EFF /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | BUNDLE_LOADER = "$(TEST_HOST)"; 511 | FRAMEWORK_SEARCH_PATHS = ( 512 | "$(SDKROOT)/Developer/Library/Frameworks", 513 | "$(inherited)", 514 | ); 515 | INFOPLIST_FILE = OperationQueuesTests/Info.plist; 516 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 517 | PRODUCT_NAME = "$(TARGET_NAME)"; 518 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OperationQueues.app/OperationQueues"; 519 | }; 520 | name = Release; 521 | }; 522 | /* End XCBuildConfiguration section */ 523 | 524 | /* Begin XCConfigurationList section */ 525 | 249B412D1B6C960B00870EFF /* Build configuration list for PBXProject "OperationQueues" */ = { 526 | isa = XCConfigurationList; 527 | buildConfigurations = ( 528 | 249B41531B6C960B00870EFF /* Debug */, 529 | 249B41541B6C960B00870EFF /* Release */, 530 | ); 531 | defaultConfigurationIsVisible = 0; 532 | defaultConfigurationName = Release; 533 | }; 534 | 249B41551B6C960B00870EFF /* Build configuration list for PBXNativeTarget "OperationQueues" */ = { 535 | isa = XCConfigurationList; 536 | buildConfigurations = ( 537 | 249B41561B6C960B00870EFF /* Debug */, 538 | 249B41571B6C960B00870EFF /* Release */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | 249B41581B6C960B00870EFF /* Build configuration list for PBXNativeTarget "OperationQueuesTests" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | 249B41591B6C960B00870EFF /* Debug */, 547 | 249B415A1B6C960B00870EFF /* Release */, 548 | ); 549 | defaultConfigurationIsVisible = 0; 550 | defaultConfigurationName = Release; 551 | }; 552 | /* End XCConfigurationList section */ 553 | }; 554 | rootObject = 249B412A1B6C960B00870EFF /* Project object */; 555 | } 556 | -------------------------------------------------------------------------------- /OperationQueues.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OperationQueues/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /OperationQueues/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 18 | return YES; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /OperationQueues/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /OperationQueues/Base.lproj/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 | -------------------------------------------------------------------------------- /OperationQueues/CustomOperation/OQConcurrentOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQConcurrentOperation.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQConcurrentOperation : NSOperation 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /OperationQueues/CustomOperation/OQConcurrentOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQConcurrentOperation.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQConcurrentOperation.h" 10 | 11 | @implementation OQConcurrentOperation 12 | 13 | @synthesize executing = _executing; 14 | @synthesize finished = _finished; 15 | 16 | - (id)init { 17 | self = [super init]; 18 | if (self) { 19 | _executing = NO; 20 | _finished = NO; 21 | } 22 | return self; 23 | } 24 | 25 | - (BOOL)isConcurrent { 26 | return YES; 27 | } 28 | 29 | - (BOOL)isExecuting { 30 | return _executing; 31 | } 32 | 33 | - (BOOL)isFinished { 34 | return _finished; 35 | } 36 | 37 | - (void)start { 38 | if (self.isCancelled) { 39 | [self willChangeValueForKey:@"isFinished"]; 40 | _finished = YES; 41 | [self didChangeValueForKey:@"isFinished"]; 42 | 43 | return; 44 | } 45 | 46 | [self willChangeValueForKey:@"isExecuting"]; 47 | 48 | [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]; 49 | _executing = YES; 50 | 51 | [self didChangeValueForKey:@"isExecuting"]; 52 | } 53 | 54 | - (void)main { 55 | @try { 56 | NSLog(@"Start executing %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), [NSThread mainThread], [NSThread currentThread]); 57 | 58 | sleep(3); 59 | 60 | [self willChangeValueForKey:@"isExecuting"]; 61 | _executing = NO; 62 | [self didChangeValueForKey:@"isExecuting"]; 63 | 64 | [self willChangeValueForKey:@"isFinished"]; 65 | _finished = YES; 66 | [self didChangeValueForKey:@"isFinished"]; 67 | 68 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 69 | } 70 | @catch (NSException *exception) { 71 | NSLog(@"Exception: %@", exception); 72 | } 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /OperationQueues/CustomOperation/OQNonConcurrentOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQNonConcurrentOperation.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQNonConcurrentOperation : NSOperation 12 | 13 | - (instancetype)initWithData:(id)data; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OperationQueues/CustomOperation/OQNonConcurrentOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQNonConcurrentOperation.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQNonConcurrentOperation.h" 10 | 11 | @interface OQNonConcurrentOperation () 12 | 13 | @property (strong, nonatomic) id data; 14 | 15 | @end 16 | 17 | @implementation OQNonConcurrentOperation 18 | 19 | - (id)initWithData:(id)data { 20 | self = [super init]; 21 | if (self) { 22 | self.data = data; 23 | } 24 | return self; 25 | } 26 | 27 | /* 28 | /// 不支持取消操作 29 | - (void)main { 30 | @try { 31 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), self.data, [NSThread mainThread], [NSThread currentThread]); 32 | sleep(3); 33 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 34 | } 35 | @catch(NSException *exception) { 36 | NSLog(@"Exception: %@", exception); 37 | } 38 | } 39 | */ 40 | 41 | /// 支持取消操作 42 | - (void)main { 43 | @try { 44 | if (self.isCancelled) return; 45 | 46 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), self.data, [NSThread mainThread], [NSThread currentThread]); 47 | 48 | for (NSUInteger i = 0; i < 3; i++) { 49 | if (self.isCancelled) return; 50 | 51 | sleep(1); 52 | 53 | NSLog(@"Loop %@", @(i + 1)); 54 | } 55 | 56 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 57 | } 58 | @catch(NSException *exception) { 59 | NSLog(@"Exception: %@", exception); 60 | } 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /OperationQueues/ExecuteOperation/OQManualExecuteOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQManualExecuteOperation.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQManualExecuteOperation : NSObject 12 | 13 | - (BOOL)manualPerformOperation:(NSOperation *)operation; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OperationQueues/ExecuteOperation/OQManualExecuteOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQManualExecuteOperation.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQManualExecuteOperation.h" 10 | 11 | @implementation OQManualExecuteOperation 12 | 13 | - (BOOL)manualPerformOperation:(NSOperation *)operation { 14 | BOOL ranIt = NO; 15 | 16 | if (operation.isCancelled) { 17 | ranIt = YES; 18 | } else if (operation.isReady) { 19 | if (!operation.isConcurrent) { 20 | [operation start]; 21 | } else { 22 | [NSThread detachNewThreadSelector:@selector(start) toTarget:operation withObject:nil]; 23 | } 24 | ranIt = YES; 25 | } 26 | 27 | return ranIt; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /OperationQueues/ExecuteOperation/OQUseOperationQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQUseOperationQueue.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQUseOperationQueue : NSObject 12 | 13 | - (void)executeOperationUsingOperationQueue; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OperationQueues/ExecuteOperation/OQUseOperationQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQUseOperationQueue.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQUseOperationQueue.h" 10 | 11 | @implementation OQUseOperationQueue 12 | 13 | - (void)executeOperationUsingOperationQueue { 14 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 15 | 16 | NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(taskMethod) object:nil]; 17 | [operationQueue addOperation:invocationOperation]; 18 | 19 | NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ 20 | NSLog(@"Start executing blockOperation1, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 21 | sleep(3); 22 | NSLog(@"Finish executing blockOperation1"); 23 | }]; 24 | 25 | NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ 26 | NSLog(@"Start executing blockOperation2, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 27 | sleep(3); 28 | NSLog(@"Finish executing blockOperation2"); 29 | }]; 30 | 31 | [operationQueue addOperations:@[ blockOperation1, blockOperation2 ] waitUntilFinished:NO]; 32 | 33 | [operationQueue addOperationWithBlock:^{ 34 | NSLog(@"Start executing block, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 35 | sleep(3); 36 | NSLog(@"Finish executing block"); 37 | }]; 38 | 39 | [operationQueue waitUntilAllOperationsAreFinished]; 40 | } 41 | 42 | - (void)taskMethod { 43 | NSLog(@"Start executing %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), [NSThread mainThread], [NSThread currentThread]); 44 | sleep(3); 45 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /OperationQueues/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /OperationQueues/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.leichunfeng.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /OperationQueues/NSBlockOperation/OQCreateBlockOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQCreateBlockOperation.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQCreateBlockOperation : NSObject 12 | 13 | - (NSBlockOperation *)blockOperation; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OperationQueues/NSBlockOperation/OQCreateBlockOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQCreateBlockOperation.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQCreateBlockOperation.h" 10 | 11 | @implementation OQCreateBlockOperation 12 | 13 | - (NSBlockOperation *)blockOperation { 14 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 15 | NSLog(@"Start executing block1, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 16 | sleep(3); 17 | NSLog(@"Finish executing block1"); 18 | }]; 19 | 20 | [blockOperation addExecutionBlock:^{ 21 | NSLog(@"Start executing block2, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 22 | sleep(3); 23 | NSLog(@"Finish executing block2"); 24 | }]; 25 | 26 | [blockOperation addExecutionBlock:^{ 27 | NSLog(@"Start executing block3, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 28 | sleep(3); 29 | NSLog(@"Finish executing block3"); 30 | }]; 31 | 32 | return blockOperation; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /OperationQueues/NSInvocationOperation/ExecuteOperation/OQManualExecuteOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQManualExecuteOperation.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQManualExecuteOperation : NSObject 12 | 13 | - (BOOL)manualPerformOperation:(NSOperation *)operation; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OperationQueues/NSInvocationOperation/ExecuteOperation/OQManualExecuteOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQManualExecuteOperation.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQManualExecuteOperation.h" 10 | 11 | @implementation OQManualExecuteOperation 12 | 13 | - (BOOL)manualPerformOperation:(NSOperation *)operation { 14 | BOOL ranIt = NO; 15 | 16 | if (operation.isCancelled) { 17 | ranIt = YES; 18 | } else if (operation.isReady) { 19 | if (![operation isConcurrent]) { 20 | [operation start]; 21 | } else { 22 | [NSThread detachNewThreadSelector:@selector(start) toTarget:operation withObject:nil]; 23 | } 24 | ranIt = YES; 25 | } 26 | 27 | return ranIt; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /OperationQueues/NSInvocationOperation/ExecuteOperation/OQUseOperationQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQUseOperationQueue.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQUseOperationQueue : NSObject 12 | 13 | - (void)executeOperationsUsingOperationQueue; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OperationQueues/NSInvocationOperation/ExecuteOperation/OQUseOperationQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQUseOperationQueue.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQUseOperationQueue.h" 10 | 11 | @implementation OQUseOperationQueue 12 | 13 | - (void)executeOperationsUsingOperationQueue { 14 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 15 | 16 | NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(taskMethod) object:nil]; 17 | [operationQueue addOperation:invocationOperation]; 18 | 19 | NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ 20 | NSLog(@"Start executing blockOperation1"); 21 | sleep(3); 22 | NSLog(@"Finish executing blockOperation1"); 23 | }]; 24 | 25 | NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ 26 | NSLog(@"Start executing blockOperation2"); 27 | sleep(3); 28 | NSLog(@"Finish executing blockOperation2"); 29 | }]; 30 | 31 | [operationQueue addOperations:@[ blockOperation1, blockOperation2 ] waitUntilFinished:NO]; 32 | 33 | [operationQueue addOperationWithBlock:^{ 34 | NSLog(@"Start executing block"); 35 | sleep(3); 36 | NSLog(@"Finish executing block"); 37 | }]; 38 | 39 | [operationQueue waitUntilAllOperationsAreFinished]; 40 | } 41 | 42 | - (void)taskMethod { 43 | NSLog(@"Start executing taskMethod"); 44 | sleep(3); 45 | NSLog(@"Finish executing taskMethod"); 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /OperationQueues/NSInvocationOperation/OQCreateInvocationOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // OQCreateInvocationOperation.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OQCreateInvocationOperation : NSObject 12 | 13 | - (NSInvocationOperation *)invocationOperationWithData:(id)data; 14 | - (NSInvocationOperation *)invocationOperationWithData:(id)data userInput:(NSString *)userInput; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /OperationQueues/NSInvocationOperation/OQCreateInvocationOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQCreateInvocationOperation.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "OQCreateInvocationOperation.h" 10 | 11 | @implementation OQCreateInvocationOperation 12 | 13 | - (NSInvocationOperation *)invocationOperationWithData:(id)data { 14 | return [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod1:) object:data]; 15 | } 16 | 17 | - (NSInvocationOperation *)invocationOperationWithData:(id)data userInput:(NSString *)userInput { 18 | NSInvocationOperation *invocationOperation = [self invocationOperationWithData:data]; 19 | 20 | if (userInput.length == 0) { 21 | invocationOperation.invocation.selector = @selector(myTaskMethod2:); 22 | } 23 | 24 | return invocationOperation; 25 | } 26 | 27 | - (void)myTaskMethod1:(id)data { 28 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), data, [NSThread mainThread], [NSThread currentThread]); 29 | sleep(3); 30 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 31 | } 32 | 33 | - (void)myTaskMethod2:(id)data { 34 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), data, [NSThread mainThread], [NSThread currentThread]); 35 | sleep(3); 36 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /OperationQueues/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /OperationQueues/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /OperationQueues/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /OperationQueuesTests/CustomOperation/OQConcurrentOperationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQConcurrentOperationTests.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OQConcurrentOperation.h" 12 | 13 | @interface OQConcurrentOperationTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OQConcurrentOperationTests 18 | 19 | - (void)testConcurrentOperation { 20 | OQConcurrentOperation *concurrentOperation = [[OQConcurrentOperation alloc] init]; 21 | [concurrentOperation start]; 22 | [concurrentOperation waitUntilFinished]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /OperationQueuesTests/CustomOperation/OQNonConcurrentOperationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQNonConcurrentOperationTests.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OQNonConcurrentOperation.h" 12 | 13 | @interface OQNonConcurrentOperationTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OQNonConcurrentOperationTests 18 | 19 | - (void)testInitWithData_1 { 20 | OQNonConcurrentOperation *nonConcurrentOperation = [[OQNonConcurrentOperation alloc] initWithData:@"leichunfeng"]; 21 | [nonConcurrentOperation start]; 22 | } 23 | 24 | - (void)testInitWithData_2 { 25 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 26 | 27 | OQNonConcurrentOperation *nonConcurrentOperation = [[OQNonConcurrentOperation alloc] initWithData:@"leichunfeng"]; 28 | 29 | [operationQueue addOperation:nonConcurrentOperation]; 30 | 31 | // /* 32 | sleep(1); 33 | 34 | [nonConcurrentOperation cancel]; 35 | // */ 36 | 37 | [operationQueue waitUntilAllOperationsAreFinished]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /OperationQueuesTests/ExecuteOperation/OQManualExecuteOperationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQManualExecuteOperationTests.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OQManualExecuteOperation.h" 12 | 13 | @interface OQManualExecuteOperationTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OQManualExecuteOperationTests 18 | 19 | - (void)testManualPerformOperation { 20 | OQManualExecuteOperation *manualExecuteOperation = [[OQManualExecuteOperation alloc] init]; 21 | 22 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 23 | NSLog(@"Start executing blockOperation, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 24 | sleep(3); 25 | NSLog(@"Finish executing blockOperation"); 26 | }]; 27 | 28 | [manualExecuteOperation manualPerformOperation:blockOperation]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /OperationQueuesTests/ExecuteOperation/OQUseOperationQueueTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQUseOperationQueueTests.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/2. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OQUseOperationQueue.h" 12 | 13 | @interface OQUseOperationQueueTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OQUseOperationQueueTests 18 | 19 | - (void)testExecuteOperationUsingOperationQueue { 20 | OQUseOperationQueue *useOperationQueue = [[OQUseOperationQueue alloc] init]; 21 | [useOperationQueue executeOperationUsingOperationQueue]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /OperationQueuesTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.leichunfeng.$(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 | -------------------------------------------------------------------------------- /OperationQueuesTests/NSBlockOperation/OQCreateBlockOperationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQCreateBlockOperationTests.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OQCreateBlockOperation.h" 12 | 13 | @interface OQCreateBlockOperationTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OQCreateBlockOperationTests 18 | 19 | - (void)testBlockOperation { 20 | OQCreateBlockOperation *createBlockOperation = [[OQCreateBlockOperation alloc] init]; 21 | 22 | NSBlockOperation *blockOperation = [createBlockOperation blockOperation]; 23 | 24 | [blockOperation start]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /OperationQueuesTests/NSInvocationOperation/OQCreateInvocationOperationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OQCreateInvocationOperationTests.m 3 | // OperationQueues 4 | // 5 | // Created by leichunfeng on 15/8/1. 6 | // Copyright (c) 2015年 leichunfeng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OQCreateInvocationOperation.h" 12 | 13 | @interface OQCreateInvocationOperationTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation OQCreateInvocationOperationTests 18 | 19 | - (void)testInvocationOperationWithData { 20 | OQCreateInvocationOperation *createInvocationOperation = [[OQCreateInvocationOperation alloc] init]; 21 | 22 | NSInvocationOperation *invocationOperation = [createInvocationOperation invocationOperationWithData:@"leichunfeng"]; 23 | 24 | [invocationOperation start]; 25 | } 26 | 27 | - (void)testInvocationOperationWithData_userInput_1 { 28 | OQCreateInvocationOperation *createInvocationOperation = [[OQCreateInvocationOperation alloc] init]; 29 | 30 | NSInvocationOperation *invocationOperation = [createInvocationOperation invocationOperationWithData:@"leichunfeng" userInput:@"Hello NSInvocationOperation!"]; 31 | 32 | [invocationOperation start]; 33 | } 34 | 35 | - (void)testInvocationOperationWithData_userInput_2 { 36 | OQCreateInvocationOperation *createInvocationOperation = [[OQCreateInvocationOperation alloc] init]; 37 | 38 | NSInvocationOperation *invocationOperation = [createInvocationOperation invocationOperationWithData:@"leichunfeng" userInput:nil]; 39 | 40 | [invocationOperation start]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OperationQueues 2 | 3 | 我的博文[《iOS 并发编程之 Operation Queues》](http://blog.leichunfeng.com/blog/2015/07/29/ios-concurrency-programming-operation-queues/)的完整配套代码。 4 | 5 | 创建 NSInvocationOperation 对象: 6 | 7 | ``` objc 8 | @interface OQCreateInvocationOperation : NSObject 9 | 10 | - (NSInvocationOperation *)invocationOperationWithData:(id)data; 11 | - (NSInvocationOperation *)invocationOperationWithData:(id)data userInput:(NSString *)userInput; 12 | 13 | @end 14 | 15 | @implementation OQCreateInvocationOperation 16 | 17 | - (NSInvocationOperation *)invocationOperationWithData:(id)data { 18 | return [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod1:) object:data]; 19 | } 20 | 21 | - (NSInvocationOperation *)invocationOperationWithData:(id)data userInput:(NSString *)userInput { 22 | NSInvocationOperation *invocationOperation = [self invocationOperationWithData:data]; 23 | 24 | if (userInput.length == 0) { 25 | invocationOperation.invocation.selector = @selector(myTaskMethod2:); 26 | } 27 | 28 | return invocationOperation; 29 | } 30 | 31 | - (void)myTaskMethod1:(id)data { 32 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), data, [NSThread mainThread], [NSThread currentThread]); 33 | sleep(3); 34 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 35 | } 36 | 37 | - (void)myTaskMethod2:(id)data { 38 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), data, [NSThread mainThread], [NSThread currentThread]); 39 | sleep(3); 40 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 41 | } 42 | 43 | @end 44 | ``` 45 | 46 | 创建 NSBlockOperation 对象: 47 | 48 | ``` objc 49 | @interface OQCreateBlockOperation : NSObject 50 | 51 | - (NSBlockOperation *)blockOperation; 52 | 53 | @end 54 | 55 | @implementation OQCreateBlockOperation 56 | 57 | - (NSBlockOperation *)blockOperation { 58 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 59 | NSLog(@"Start executing block1, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 60 | sleep(3); 61 | NSLog(@"Finish executing block1"); 62 | }]; 63 | 64 | [blockOperation addExecutionBlock:^{ 65 | NSLog(@"Start executing block2, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 66 | sleep(3); 67 | NSLog(@"Finish executing block2"); 68 | }]; 69 | 70 | [blockOperation addExecutionBlock:^{ 71 | NSLog(@"Start executing block3, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 72 | sleep(3); 73 | NSLog(@"Finish executing block3"); 74 | }]; 75 | 76 | return blockOperation; 77 | } 78 | 79 | @end 80 | ``` 81 | 82 | 自定义非并发的 Operation 对象: 83 | 84 | ``` objc 85 | @interface OQNonConcurrentOperation : NSOperation 86 | 87 | - (instancetype)initWithData:(id)data; 88 | 89 | @end 90 | 91 | @interface OQNonConcurrentOperation () 92 | 93 | @property (strong, nonatomic) id data; 94 | 95 | @end 96 | 97 | @implementation OQNonConcurrentOperation 98 | 99 | - (id)initWithData:(id)data { 100 | self = [super init]; 101 | if (self) { 102 | self.data = data; 103 | } 104 | return self; 105 | } 106 | 107 | /* 108 | /// 不支持取消操作 109 | - (void)main { 110 | @try { 111 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), self.data, [NSThread mainThread], [NSThread currentThread]); 112 | sleep(3); 113 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 114 | } 115 | @catch(NSException *exception) { 116 | NSLog(@"Exception: %@", exception); 117 | } 118 | } 119 | */ 120 | 121 | /// 支持取消操作 122 | - (void)main { 123 | @try { 124 | if (self.isCancelled) return; 125 | 126 | NSLog(@"Start executing %@ with data: %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), self.data, [NSThread mainThread], [NSThread currentThread]); 127 | 128 | for (NSUInteger i = 0; i < 3; i++) { 129 | if (self.isCancelled) return; 130 | 131 | sleep(1); 132 | 133 | NSLog(@"Loop %@", @(i + 1)); 134 | } 135 | 136 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 137 | } 138 | @catch(NSException *exception) { 139 | NSLog(@"Exception: %@", exception); 140 | } 141 | } 142 | 143 | @end 144 | ``` 145 | 146 | 自定义并发的 Operation 对象: 147 | 148 | ``` objc 149 | @interface OQConcurrentOperation : NSOperation 150 | 151 | @end 152 | 153 | @implementation OQConcurrentOperation 154 | 155 | @synthesize executing = _executing; 156 | @synthesize finished = _finished; 157 | 158 | - (id)init { 159 | self = [super init]; 160 | if (self) { 161 | _executing = NO; 162 | _finished = NO; 163 | } 164 | return self; 165 | } 166 | 167 | - (BOOL)isConcurrent { 168 | return YES; 169 | } 170 | 171 | - (BOOL)isExecuting { 172 | return _executing; 173 | } 174 | 175 | - (BOOL)isFinished { 176 | return _finished; 177 | } 178 | 179 | - (void)start { 180 | if (self.isCancelled) { 181 | [self willChangeValueForKey:@"isFinished"]; 182 | _finished = YES; 183 | [self didChangeValueForKey:@"isFinished"]; 184 | 185 | return; 186 | } 187 | 188 | [self willChangeValueForKey:@"isExecuting"]; 189 | 190 | [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]; 191 | _executing = YES; 192 | 193 | [self didChangeValueForKey:@"isExecuting"]; 194 | } 195 | 196 | - (void)main { 197 | @try { 198 | NSLog(@"Start executing %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), [NSThread mainThread], [NSThread currentThread]); 199 | 200 | sleep(3); 201 | 202 | [self willChangeValueForKey:@"isExecuting"]; 203 | _executing = NO; 204 | [self didChangeValueForKey:@"isExecuting"]; 205 | 206 | [self willChangeValueForKey:@"isFinished"]; 207 | _finished = YES; 208 | [self didChangeValueForKey:@"isFinished"]; 209 | 210 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 211 | } 212 | @catch (NSException *exception) { 213 | NSLog(@"Exception: %@", exception); 214 | } 215 | } 216 | 217 | @end 218 | ``` 219 | 220 | 使用 Operation Queue 执行 Operation 对象: 221 | 222 | ``` objc 223 | @interface OQUseOperationQueue : NSObject 224 | 225 | - (void)executeOperationUsingOperationQueue; 226 | 227 | @end 228 | 229 | @implementation OQUseOperationQueue 230 | 231 | - (void)executeOperationUsingOperationQueue { 232 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 233 | 234 | NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(taskMethod) object:nil]; 235 | [operationQueue addOperation:invocationOperation]; 236 | 237 | NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ 238 | NSLog(@"Start executing blockOperation1, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 239 | sleep(3); 240 | NSLog(@"Finish executing blockOperation1"); 241 | }]; 242 | 243 | NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ 244 | NSLog(@"Start executing blockOperation2, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 245 | sleep(3); 246 | NSLog(@"Finish executing blockOperation2"); 247 | }]; 248 | 249 | [operationQueue addOperations:@[ blockOperation1, blockOperation2 ] waitUntilFinished:NO]; 250 | 251 | [operationQueue addOperationWithBlock:^{ 252 | NSLog(@"Start executing block, mainThread: %@, currentThread: %@", [NSThread mainThread], [NSThread currentThread]); 253 | sleep(3); 254 | NSLog(@"Finish executing block"); 255 | }]; 256 | 257 | [operationQueue waitUntilAllOperationsAreFinished]; 258 | } 259 | 260 | - (void)taskMethod { 261 | NSLog(@"Start executing %@, mainThread: %@, currentThread: %@", NSStringFromSelector(_cmd), [NSThread mainThread], [NSThread currentThread]); 262 | sleep(3); 263 | NSLog(@"Finish executing %@", NSStringFromSelector(_cmd)); 264 | } 265 | 266 | @end 267 | ``` 268 | 269 | 手动执行 Operation 对象: 270 | 271 | ``` objc 272 | @interface OQManualExecuteOperation : NSObject 273 | 274 | - (BOOL)manualPerformOperation:(NSOperation *)operation; 275 | 276 | @end 277 | 278 | @implementation OQManualExecuteOperation 279 | 280 | - (BOOL)manualPerformOperation:(NSOperation *)operation { 281 | BOOL ranIt = NO; 282 | 283 | if (operation.isCancelled) { 284 | ranIt = YES; 285 | } else if (operation.isReady) { 286 | if (!operation.isConcurrent) { 287 | [operation start]; 288 | } else { 289 | [NSThread detachNewThreadSelector:@selector(start) toTarget:operation withObject:nil]; 290 | } 291 | ranIt = YES; 292 | } 293 | 294 | return ranIt; 295 | } 296 | 297 | @end 298 | ``` 299 | --------------------------------------------------------------------------------