├── .gitignore ├── .travis.yml ├── AsyncBlockOperation.podspec ├── AsyncBlockOperation.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── AsyncBlockOperation.xcscheme ├── AsyncBlockOperation ├── AsyncBlockOperation.h ├── AsyncBlockOperation.m └── Info.plist ├── AsyncBlockOperationTests ├── AsyncBlockOperationTests.swift └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.pbxuser 3 | !default.pbxuser 4 | *.mode1v3 5 | !default.mode1v3 6 | *.mode2v3 7 | !default.mode2v3 8 | *.perspectivev3 9 | !default.perspectivev3 10 | xcuserdata 11 | *.xccheckout 12 | *.moved-aside 13 | DerivedData 14 | *.hmap 15 | *.ipa 16 | *.xcuserstate 17 | 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode6.4 3 | script: 4 | - xctool -scheme 'AsyncBlockOperation' -sdk iphonesimulator CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO test 5 | -------------------------------------------------------------------------------- /AsyncBlockOperation.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "AsyncBlockOperation" 3 | s.version = "1.0.1" 4 | s.summary = "NSOperation subclass for async block." 5 | s.homepage = "https://github.com/devxoul/AsyncBlockOperation" 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { "devxoul" => "devxoul@gmail.com" } 8 | s.source = { :git => "https://github.com/devxoul/AsyncBlockOperation.git", 9 | :tag => "#{s.version}" } 10 | s.requires_arc = true 11 | s.source_files = 'AsyncBlockOperation/AsyncBlockOperation.{h,m}' 12 | s.frameworks = 'Foundation' 13 | 14 | s.ios.deployment_target = '4.3' 15 | s.osx.deployment_target = '10.6' 16 | end 17 | -------------------------------------------------------------------------------- /AsyncBlockOperation.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 037493BF1B5FBC7700672D74 /* AsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 037493BE1B5FBC7700672D74 /* AsyncBlockOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 037493C51B5FBC7700672D74 /* AsyncBlockOperation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037493B91B5FBC7700672D74 /* AsyncBlockOperation.framework */; }; 12 | 037493CC1B5FBC7700672D74 /* AsyncBlockOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037493CB1B5FBC7700672D74 /* AsyncBlockOperationTests.swift */; }; 13 | 037493D81B5FC06F00672D74 /* AsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 037493D71B5FC06F00672D74 /* AsyncBlockOperation.m */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXContainerItemProxy section */ 17 | 037493C61B5FBC7700672D74 /* PBXContainerItemProxy */ = { 18 | isa = PBXContainerItemProxy; 19 | containerPortal = 037493B01B5FBC7700672D74 /* Project object */; 20 | proxyType = 1; 21 | remoteGlobalIDString = 037493B81B5FBC7700672D74; 22 | remoteInfo = AsyncBlockOperation; 23 | }; 24 | /* End PBXContainerItemProxy section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 037493B91B5FBC7700672D74 /* AsyncBlockOperation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncBlockOperation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 037493BD1B5FBC7700672D74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 037493BE1B5FBC7700672D74 /* AsyncBlockOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncBlockOperation.h; sourceTree = ""; }; 30 | 037493C41B5FBC7700672D74 /* AsyncBlockOperationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AsyncBlockOperationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 037493CA1B5FBC7700672D74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 037493CB1B5FBC7700672D74 /* AsyncBlockOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncBlockOperationTests.swift; sourceTree = ""; }; 33 | 037493D71B5FC06F00672D74 /* AsyncBlockOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncBlockOperation.m; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 037493B51B5FBC7700672D74 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | 037493C11B5FBC7700672D74 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | 037493C51B5FBC7700672D74 /* AsyncBlockOperation.framework in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 037493AF1B5FBC7700672D74 = { 56 | isa = PBXGroup; 57 | children = ( 58 | 037493BB1B5FBC7700672D74 /* AsyncBlockOperation */, 59 | 037493C81B5FBC7700672D74 /* AsyncBlockOperationTests */, 60 | 037493BA1B5FBC7700672D74 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | 037493BA1B5FBC7700672D74 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 037493B91B5FBC7700672D74 /* AsyncBlockOperation.framework */, 68 | 037493C41B5FBC7700672D74 /* AsyncBlockOperationTests.xctest */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 037493BB1B5FBC7700672D74 /* AsyncBlockOperation */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 037493BE1B5FBC7700672D74 /* AsyncBlockOperation.h */, 77 | 037493D71B5FC06F00672D74 /* AsyncBlockOperation.m */, 78 | 037493BC1B5FBC7700672D74 /* Supporting Files */, 79 | ); 80 | path = AsyncBlockOperation; 81 | sourceTree = ""; 82 | }; 83 | 037493BC1B5FBC7700672D74 /* Supporting Files */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 037493BD1B5FBC7700672D74 /* Info.plist */, 87 | ); 88 | name = "Supporting Files"; 89 | sourceTree = ""; 90 | }; 91 | 037493C81B5FBC7700672D74 /* AsyncBlockOperationTests */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 037493CB1B5FBC7700672D74 /* AsyncBlockOperationTests.swift */, 95 | 037493C91B5FBC7700672D74 /* Supporting Files */, 96 | ); 97 | path = AsyncBlockOperationTests; 98 | sourceTree = ""; 99 | }; 100 | 037493C91B5FBC7700672D74 /* Supporting Files */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 037493CA1B5FBC7700672D74 /* Info.plist */, 104 | ); 105 | name = "Supporting Files"; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXHeadersBuildPhase section */ 111 | 037493B61B5FBC7700672D74 /* Headers */ = { 112 | isa = PBXHeadersBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 037493BF1B5FBC7700672D74 /* AsyncBlockOperation.h in Headers */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXHeadersBuildPhase section */ 120 | 121 | /* Begin PBXNativeTarget section */ 122 | 037493B81B5FBC7700672D74 /* AsyncBlockOperation */ = { 123 | isa = PBXNativeTarget; 124 | buildConfigurationList = 037493CF1B5FBC7700672D74 /* Build configuration list for PBXNativeTarget "AsyncBlockOperation" */; 125 | buildPhases = ( 126 | 037493B41B5FBC7700672D74 /* Sources */, 127 | 037493B51B5FBC7700672D74 /* Frameworks */, 128 | 037493B61B5FBC7700672D74 /* Headers */, 129 | 037493B71B5FBC7700672D74 /* Resources */, 130 | ); 131 | buildRules = ( 132 | ); 133 | dependencies = ( 134 | ); 135 | name = AsyncBlockOperation; 136 | productName = AsyncBlockOperation; 137 | productReference = 037493B91B5FBC7700672D74 /* AsyncBlockOperation.framework */; 138 | productType = "com.apple.product-type.framework"; 139 | }; 140 | 037493C31B5FBC7700672D74 /* AsyncBlockOperationTests */ = { 141 | isa = PBXNativeTarget; 142 | buildConfigurationList = 037493D21B5FBC7700672D74 /* Build configuration list for PBXNativeTarget "AsyncBlockOperationTests" */; 143 | buildPhases = ( 144 | 037493C01B5FBC7700672D74 /* Sources */, 145 | 037493C11B5FBC7700672D74 /* Frameworks */, 146 | 037493C21B5FBC7700672D74 /* Resources */, 147 | ); 148 | buildRules = ( 149 | ); 150 | dependencies = ( 151 | 037493C71B5FBC7700672D74 /* PBXTargetDependency */, 152 | ); 153 | name = AsyncBlockOperationTests; 154 | productName = AsyncBlockOperationTests; 155 | productReference = 037493C41B5FBC7700672D74 /* AsyncBlockOperationTests.xctest */; 156 | productType = "com.apple.product-type.bundle.unit-test"; 157 | }; 158 | /* End PBXNativeTarget section */ 159 | 160 | /* Begin PBXProject section */ 161 | 037493B01B5FBC7700672D74 /* Project object */ = { 162 | isa = PBXProject; 163 | attributes = { 164 | LastUpgradeCheck = 0640; 165 | ORGANIZATIONNAME = "Suyeol Jeon"; 166 | TargetAttributes = { 167 | 037493B81B5FBC7700672D74 = { 168 | CreatedOnToolsVersion = 6.4; 169 | }; 170 | 037493C31B5FBC7700672D74 = { 171 | CreatedOnToolsVersion = 6.4; 172 | }; 173 | }; 174 | }; 175 | buildConfigurationList = 037493B31B5FBC7700672D74 /* Build configuration list for PBXProject "AsyncBlockOperation" */; 176 | compatibilityVersion = "Xcode 3.2"; 177 | developmentRegion = English; 178 | hasScannedForEncodings = 0; 179 | knownRegions = ( 180 | en, 181 | ); 182 | mainGroup = 037493AF1B5FBC7700672D74; 183 | productRefGroup = 037493BA1B5FBC7700672D74 /* Products */; 184 | projectDirPath = ""; 185 | projectRoot = ""; 186 | targets = ( 187 | 037493B81B5FBC7700672D74 /* AsyncBlockOperation */, 188 | 037493C31B5FBC7700672D74 /* AsyncBlockOperationTests */, 189 | ); 190 | }; 191 | /* End PBXProject section */ 192 | 193 | /* Begin PBXResourcesBuildPhase section */ 194 | 037493B71B5FBC7700672D74 /* Resources */ = { 195 | isa = PBXResourcesBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | 037493C21B5FBC7700672D74 /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | 037493B41B5FBC7700672D74 /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 037493D81B5FC06F00672D74 /* AsyncBlockOperation.m in Sources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | 037493C01B5FBC7700672D74 /* Sources */ = { 220 | isa = PBXSourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 037493CC1B5FBC7700672D74 /* AsyncBlockOperationTests.swift in Sources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXSourcesBuildPhase section */ 228 | 229 | /* Begin PBXTargetDependency section */ 230 | 037493C71B5FBC7700672D74 /* PBXTargetDependency */ = { 231 | isa = PBXTargetDependency; 232 | target = 037493B81B5FBC7700672D74 /* AsyncBlockOperation */; 233 | targetProxy = 037493C61B5FBC7700672D74 /* PBXContainerItemProxy */; 234 | }; 235 | /* End PBXTargetDependency section */ 236 | 237 | /* Begin XCBuildConfiguration section */ 238 | 037493CD1B5FBC7700672D74 /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ALWAYS_SEARCH_USER_PATHS = NO; 242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 243 | CLANG_CXX_LIBRARY = "libc++"; 244 | CLANG_ENABLE_MODULES = YES; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_WARN_BOOL_CONVERSION = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 253 | CLANG_WARN_UNREACHABLE_CODE = YES; 254 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 255 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 256 | COPY_PHASE_STRIP = NO; 257 | CURRENT_PROJECT_VERSION = 1; 258 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 259 | ENABLE_STRICT_OBJC_MSGSEND = YES; 260 | GCC_C_LANGUAGE_STANDARD = gnu99; 261 | GCC_DYNAMIC_NO_PIC = NO; 262 | GCC_NO_COMMON_BLOCKS = YES; 263 | GCC_OPTIMIZATION_LEVEL = 0; 264 | GCC_PREPROCESSOR_DEFINITIONS = ( 265 | "DEBUG=1", 266 | "$(inherited)", 267 | ); 268 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 276 | MTL_ENABLE_DEBUG_INFO = YES; 277 | ONLY_ACTIVE_ARCH = YES; 278 | SDKROOT = iphoneos; 279 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 280 | TARGETED_DEVICE_FAMILY = "1,2"; 281 | VERSIONING_SYSTEM = "apple-generic"; 282 | VERSION_INFO_PREFIX = ""; 283 | }; 284 | name = Debug; 285 | }; 286 | 037493CE1B5FBC7700672D74 /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ALWAYS_SEARCH_USER_PATHS = NO; 290 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 291 | CLANG_CXX_LIBRARY = "libc++"; 292 | CLANG_ENABLE_MODULES = YES; 293 | CLANG_ENABLE_OBJC_ARC = YES; 294 | CLANG_WARN_BOOL_CONVERSION = YES; 295 | CLANG_WARN_CONSTANT_CONVERSION = YES; 296 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 297 | CLANG_WARN_EMPTY_BODY = YES; 298 | CLANG_WARN_ENUM_CONVERSION = YES; 299 | CLANG_WARN_INT_CONVERSION = YES; 300 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 301 | CLANG_WARN_UNREACHABLE_CODE = YES; 302 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 303 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 304 | COPY_PHASE_STRIP = NO; 305 | CURRENT_PROJECT_VERSION = 1; 306 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 307 | ENABLE_NS_ASSERTIONS = NO; 308 | ENABLE_STRICT_OBJC_MSGSEND = YES; 309 | GCC_C_LANGUAGE_STANDARD = gnu99; 310 | GCC_NO_COMMON_BLOCKS = YES; 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 313 | GCC_WARN_UNDECLARED_SELECTOR = YES; 314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 315 | GCC_WARN_UNUSED_FUNCTION = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 318 | MTL_ENABLE_DEBUG_INFO = NO; 319 | SDKROOT = iphoneos; 320 | TARGETED_DEVICE_FAMILY = "1,2"; 321 | VALIDATE_PRODUCT = YES; 322 | VERSIONING_SYSTEM = "apple-generic"; 323 | VERSION_INFO_PREFIX = ""; 324 | }; 325 | name = Release; 326 | }; 327 | 037493D01B5FBC7700672D74 /* Debug */ = { 328 | isa = XCBuildConfiguration; 329 | buildSettings = { 330 | CLANG_ENABLE_MODULES = YES; 331 | DEFINES_MODULE = YES; 332 | DYLIB_COMPATIBILITY_VERSION = 1; 333 | DYLIB_CURRENT_VERSION = 1; 334 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 335 | INFOPLIST_FILE = AsyncBlockOperation/Info.plist; 336 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 337 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 338 | PRODUCT_NAME = "$(TARGET_NAME)"; 339 | SKIP_INSTALL = YES; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 341 | }; 342 | name = Debug; 343 | }; 344 | 037493D11B5FBC7700672D74 /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | CLANG_ENABLE_MODULES = YES; 348 | DEFINES_MODULE = YES; 349 | DYLIB_COMPATIBILITY_VERSION = 1; 350 | DYLIB_CURRENT_VERSION = 1; 351 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 352 | INFOPLIST_FILE = AsyncBlockOperation/Info.plist; 353 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 355 | PRODUCT_NAME = "$(TARGET_NAME)"; 356 | SKIP_INSTALL = YES; 357 | }; 358 | name = Release; 359 | }; 360 | 037493D31B5FBC7700672D74 /* Debug */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | FRAMEWORK_SEARCH_PATHS = ( 364 | "$(SDKROOT)/Developer/Library/Frameworks", 365 | "$(inherited)", 366 | ); 367 | GCC_PREPROCESSOR_DEFINITIONS = ( 368 | "DEBUG=1", 369 | "$(inherited)", 370 | ); 371 | INFOPLIST_FILE = AsyncBlockOperationTests/Info.plist; 372 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 373 | PRODUCT_NAME = "$(TARGET_NAME)"; 374 | }; 375 | name = Debug; 376 | }; 377 | 037493D41B5FBC7700672D74 /* Release */ = { 378 | isa = XCBuildConfiguration; 379 | buildSettings = { 380 | FRAMEWORK_SEARCH_PATHS = ( 381 | "$(SDKROOT)/Developer/Library/Frameworks", 382 | "$(inherited)", 383 | ); 384 | INFOPLIST_FILE = AsyncBlockOperationTests/Info.plist; 385 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | }; 388 | name = Release; 389 | }; 390 | /* End XCBuildConfiguration section */ 391 | 392 | /* Begin XCConfigurationList section */ 393 | 037493B31B5FBC7700672D74 /* Build configuration list for PBXProject "AsyncBlockOperation" */ = { 394 | isa = XCConfigurationList; 395 | buildConfigurations = ( 396 | 037493CD1B5FBC7700672D74 /* Debug */, 397 | 037493CE1B5FBC7700672D74 /* Release */, 398 | ); 399 | defaultConfigurationIsVisible = 0; 400 | defaultConfigurationName = Release; 401 | }; 402 | 037493CF1B5FBC7700672D74 /* Build configuration list for PBXNativeTarget "AsyncBlockOperation" */ = { 403 | isa = XCConfigurationList; 404 | buildConfigurations = ( 405 | 037493D01B5FBC7700672D74 /* Debug */, 406 | 037493D11B5FBC7700672D74 /* Release */, 407 | ); 408 | defaultConfigurationIsVisible = 0; 409 | }; 410 | 037493D21B5FBC7700672D74 /* Build configuration list for PBXNativeTarget "AsyncBlockOperationTests" */ = { 411 | isa = XCConfigurationList; 412 | buildConfigurations = ( 413 | 037493D31B5FBC7700672D74 /* Debug */, 414 | 037493D41B5FBC7700672D74 /* Release */, 415 | ); 416 | defaultConfigurationIsVisible = 0; 417 | }; 418 | /* End XCConfigurationList section */ 419 | }; 420 | rootObject = 037493B01B5FBC7700672D74 /* Project object */; 421 | } 422 | -------------------------------------------------------------------------------- /AsyncBlockOperation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AsyncBlockOperation.xcodeproj/xcshareddata/xcschemes/AsyncBlockOperation.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 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /AsyncBlockOperation/AsyncBlockOperation.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Suyeol Jeon (xoul.kr) 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 | #import 24 | 25 | FOUNDATION_EXPORT double AsyncBlockOperationVersionNumber; 26 | FOUNDATION_EXPORT const unsigned char AsyncBlockOperationVersionString[]; 27 | 28 | 29 | @class AsyncBlockOperation; 30 | typedef void (^AsyncBlock)(AsyncBlockOperation * __nonnull); 31 | 32 | @interface AsyncBlockOperation : NSOperation 33 | 34 | @property (nonatomic, assign) BOOL isExecuting; 35 | @property (nonatomic, assign) BOOL isFinished; 36 | @property (nonatomic, strong, nullable) AsyncBlock block; 37 | 38 | - (nonnull instancetype)initWithBlock:(nonnull AsyncBlock)block; 39 | + (nonnull instancetype)blockOperationWithBlock:(nonnull AsyncBlock)block; 40 | - (void)complete; 41 | 42 | @end 43 | 44 | 45 | @interface NSOperationQueue (AsyncBlockOperation) 46 | 47 | - (void)addOperationWithAsyncBlock:(nonnull AsyncBlock)block; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /AsyncBlockOperation/AsyncBlockOperation.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Suyeol Jeon (xoul.kr) 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 | #import "AsyncBlockOperation.h" 24 | 25 | #pragma mark - AsyncBlockOperation 26 | 27 | @implementation AsyncBlockOperation 28 | 29 | - (nonnull instancetype)initWithBlock:(nonnull AsyncBlock)block { 30 | self = [super init]; 31 | if (self) { 32 | self.block = block; 33 | } 34 | return self; 35 | } 36 | 37 | + (nonnull instancetype)blockOperationWithBlock:(nonnull AsyncBlock)block { 38 | AsyncBlockOperation *operation = [[AsyncBlockOperation alloc] initWithBlock:block]; 39 | return operation; 40 | } 41 | 42 | - (void)start { 43 | [self willChangeValueForKey:@"isExecuting"]; 44 | self.isExecuting = YES; 45 | [self didChangeValueForKey:@"isExecuting"]; 46 | 47 | if (self.block) { 48 | self.block(self); 49 | } else { 50 | [self complete]; 51 | } 52 | } 53 | 54 | - (void)complete { 55 | [self willChangeValueForKey:@"isExecuting"]; 56 | [self willChangeValueForKey:@"isFinished"]; 57 | self.isExecuting = NO; 58 | self.isFinished = YES; 59 | [self didChangeValueForKey:@"isExecuting"]; 60 | [self didChangeValueForKey:@"isFinished"]; 61 | } 62 | 63 | @end 64 | 65 | 66 | #pragma mark - NSOperationQueue+AsyncBlockOperation 67 | 68 | @implementation NSOperationQueue (AsyncBlockOperation) 69 | 70 | - (void)addOperationWithAsyncBlock:(nonnull AsyncBlock)block { 71 | AsyncBlockOperation *operation = [AsyncBlockOperation blockOperationWithBlock:block]; 72 | [self addOperation:operation]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /AsyncBlockOperation/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | kr.xoul.$(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 | -------------------------------------------------------------------------------- /AsyncBlockOperationTests/AsyncBlockOperationTests.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Suyeol Jeon (xoul.kr) 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 | import AsyncBlockOperation 24 | import XCTest 25 | 26 | class AsyncBlockOperationTests: XCTestCase { 27 | 28 | func delay(delay: Double, _ closure: () -> Void) { 29 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) 30 | dispatch_after(time, dispatch_get_main_queue(), closure) 31 | } 32 | 33 | func testAddOperationWithAsyncBlock() { 34 | let queue = NSOperationQueue() 35 | queue.maxConcurrentOperationCount = 0 36 | queue.addOperation(AsyncBlockOperation { _ in }) 37 | queue.addOperationWithAsyncBlock { _ in } 38 | queue.addOperationWithAsyncBlock { _ in } 39 | XCTAssertEqual(queue.operationCount, 3) 40 | } 41 | 42 | func testCallComplete() { 43 | let expectation = self.expectationWithDescription("Test") 44 | var flag = false 45 | 46 | let queue = NSOperationQueue() 47 | queue.maxConcurrentOperationCount = 1 48 | queue.addOperationWithAsyncBlock { op in 49 | flag = true 50 | op.complete() 51 | } 52 | queue.addOperationWithAsyncBlock { op in 53 | XCTAssertTrue(flag) 54 | expectation.fulfill() 55 | } 56 | self.waitForExpectationsWithTimeout(0.5, handler: nil) 57 | } 58 | 59 | func testNotCallComplete() { 60 | let expectation = self.expectationWithDescription("Test") 61 | var flag = false 62 | 63 | let queue = NSOperationQueue() 64 | queue.maxConcurrentOperationCount = 1 65 | queue.addOperationWithAsyncBlock { op in 66 | // do not call op.complete() 67 | } 68 | queue.addOperationWithAsyncBlock { op in 69 | flag = true 70 | } 71 | self.delay(0.5) { 72 | XCTAssertFalse(flag) 73 | expectation.fulfill() 74 | } 75 | self.waitForExpectationsWithTimeout(1, handler: nil) 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /AsyncBlockOperationTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | kr.xoul.$(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 Suyeol Jeon (xoul.kr) 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 | AsyncBlockOperation 2 | =================== 3 | 4 | [![Build Status](https://travis-ci.org/devxoul/AsyncBlockOperation.svg)](https://travis-ci.org/devxoul/AsyncBlockOperation) 5 | [![CocoaPods](http://img.shields.io/cocoapods/v/AsyncBlockOperation.svg?style=flat)](https://cocoapods.org/pods/AsyncBlockOperation) 6 | 7 | NSOperation subclass for async block. 8 | 9 | * [x] Both compatible with Swift and Objective-C. 10 | * [x] Light-weight. (4KB source code. Oh my god.) 11 | * [x] Short-hand method extension `NSOperationQueue`. 12 | 13 | 14 | At a Glance 15 | ----------- 16 | 17 | **Swift** 18 | 19 | ```swift 20 | import AsyncBlockOperation 21 | 22 | let operation = AsyncBlockOperation { op in 23 | doSomeAsyncTaskWithCompletionBlock { 24 | op.complete() // complete operation 25 | } 26 | } 27 | queue.addOperation(operation) 28 | ``` 29 | 30 | **Objective-C** 31 | 32 | ```objc 33 | #import 34 | 35 | AsyncBlockOperation *operation = [AsyncBlockOperation blockOperationWithBlock:^(AsyncBlockOperation *op) { 36 | [self doSomeAsyncTaskWithCompletionBlock:^{ 37 | [op complete]; // complete operation 38 | }]; 39 | }]; 40 | [queue addOperation:operation]; 41 | ``` 42 | 43 | 44 | Short-hand Method Extension 45 | --------------------------- 46 | 47 | As `NSBlockOperation` does, `AsyncBlockOperation` supports `NSOperationQueue` extension to add async block operations quickly. 48 | 49 | **Swift** 50 | 51 | ```swift 52 | queue.addOperationWithAsyncBlock { op in 53 | op.complete() 54 | } 55 | ``` 56 | 57 | **Objective-C** 58 | 59 | ```objc 60 | [queue addOperationWithAsyncBlock:^(AsyncBlockOperation *op) { 61 | [op complete]; 62 | }]; 63 | ``` 64 | 65 | 66 | Further Reading 67 | --------------- 68 | 69 | Wanna get callback after all operations are done? Consider using [NSOperationQueue+CompletionBlock](https://github.com/devxoul/NSOperationQueue-CompletionBlock) which provides `completionHandler` for `NSOperationQueue`. 70 | 71 | For example: 72 | 73 | ```swift 74 | let queue = NSOperationQueue() 75 | queue.completionHandler = { 76 | println("All images are loaded!") 77 | } 78 | queue.addOperationWithAsyncBlock { op in 79 | loadImage(imageURL1) { image in 80 | image.append(image) 81 | op.complete() 82 | } 83 | } 84 | queue.addOperationWithAsyncBlock { op in 85 | loadImage(imageURL2) { image in 86 | image.append(image) 87 | op.complete() 88 | } 89 | } 90 | ``` 91 | 92 | 93 | Installation 94 | ------------ 95 | 96 | I recommend you to use [CocoaPods](https://cocoapods.org), a dependency manager for Cocoa. 97 | 98 | **Podfile** 99 | 100 | ```ruby 101 | pod 'AsyncBlockOperation', '~> 1.0' 102 | ``` 103 | 104 | 105 | License 106 | ------- 107 | 108 | **AsyncBlockOperation** is under MIT license. See the LICENSE file for more info. 109 | --------------------------------------------------------------------------------