├── Sample ARC ├── Sample ARC │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── SFAppDelegate.h │ ├── main.m │ ├── Sample ARC-Prefix.pch │ ├── Sample ARC-Info.plist │ └── SFAppDelegate.m ├── Sample ARCTests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Sample_ARCTests.h │ ├── Sample_ARCTests.m │ └── Sample ARCTests-Info.plist └── Sample ARC.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── Sample Project ├── Sample Project │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── SFAppDelegate.h │ ├── main.m │ ├── Sample Project-Prefix.pch │ ├── Sample Project-Info.plist │ └── SFAppDelegate.m ├── Sample ProjectTests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Sample_ProjectTests.h │ ├── Sample ProjectTests-Info.plist │ └── Sample_ProjectTests.m └── Sample Project.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── SFObservers ├── NSObject+SFObservers.h ├── NSNotificationCenter+SFObservers.h ├── SFExecuteOnDealloc │ ├── NSObject+SFExecuteOnDealloc.h │ └── NSObject+SFExecuteOnDealloc.m ├── SFObservers.h ├── NSObject+SFObservers.m └── NSNotificationCenter+SFObservers.m ├── .gitignore ├── LICENCE.txt └── README.md /Sample ARC/Sample ARC/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARCTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Sample Project/Sample Project/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Sample Project/Sample ProjectTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /SFObservers/NSObject+SFObservers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by merowing2 on 3/25/12. 3 | // 4 | // 5 | // 6 | #import 7 | #import "SFObservers.h" 8 | 9 | @interface NSObject (SFObservers) 10 | @end -------------------------------------------------------------------------------- /SFObservers/NSNotificationCenter+SFObservers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by krzysztof.zablocki on 3/23/12. 3 | // 4 | // 5 | // 6 | #import 7 | #import "SFObservers.h" 8 | 9 | @interface NSNotificationCenter (SFObservers) 10 | @end -------------------------------------------------------------------------------- /Sample ARC/Sample ARC.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample Project/Sample Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARCTests/Sample_ARCTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample_ARCTests.h 3 | // Sample ARCTests 4 | // 5 | // Created by roche on 3/28/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Sample_ARCTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Sample Project/Sample ProjectTests/Sample_ProjectTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample_ProjectTests.h 3 | // Sample ProjectTests 4 | // 5 | // Created by Krzysztof Zablocki on 3/26/12. 6 | // Copyright (c) 2012 private. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Sample_ProjectTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARC/SFAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SFAppDelegate.h 3 | // Sample ARC 4 | // 5 | // Created by roche on 3/28/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SFAppDelegate : UIResponder 12 | 13 | @property(strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Sample Project/Sample Project/SFAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SFAppDelegate.h 3 | // Sample Project 4 | // 5 | // Created by Krzysztof Zablocki on 3/26/12. 6 | // Copyright (c) 2012 private. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SFAppDelegate : UIResponder 12 | 13 | @property(strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARC/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Sample ARC 4 | // 5 | // Created by roche on 3/28/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "SFAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SFAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sample Project/Sample Project/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Sample Project 4 | // 5 | // Created by Krzysztof Zablocki on 3/26/12. 6 | // Copyright (c) 2012 private. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "SFAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SFAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sample Project/Sample Project/Sample Project-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Sample Project' target in the 'Sample Project' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #define SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 1 13 | #import 14 | #import 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARC/Sample ARC-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Sample ARC' target in the 'Sample ARC' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #define SF_OBSERVERS_LOG_ORIGINAL_METHODS 1 13 | #define SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 1 14 | 15 | #import 16 | #import 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARCTests/Sample_ARCTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample_ARCTests.m 3 | // Sample ARCTests 4 | // 5 | // Created by roche on 3/28/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "Sample_ARCTests.h" 10 | 11 | @implementation Sample_ARCTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARCTests/Sample ARCTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pl.pixle.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sample Project/Sample ProjectTests/Sample ProjectTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pixle.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # found at http://blog.illuminex.com/2009/10/better-sample-gitignore-file-for-xcode.html 2 | # Mac OS X Finder and whatnot 3 | .DS_Store 4 | 5 | 6 | # Sparkle distribution Private Key (Don't check me in!) 7 | dsa_priv.pem 8 | 9 | 10 | # XCode (and ancestors) per-user config (very noisy, and not relevant) 11 | *.mode1 12 | *.mode1v3 13 | *.mode2v3 14 | *.perspective 15 | *.perspectivev3 16 | *.pbxuser 17 | *.xcuserdata 18 | 19 | # Generated files 20 | VersionX-revision.h 21 | 22 | 23 | # build products 24 | build/ 25 | *.[oa] 26 | 27 | 28 | # Other source repository archive directories (protects when importing) 29 | .hg 30 | .svn 31 | CVS 32 | 33 | 34 | # automatic backup files 35 | *~.nib 36 | *.swp 37 | *~ 38 | *(Autosaved).rtfd/ 39 | Backup[ ]of[ ]*.pages/ 40 | Backup[ ]of[ ]*.key/ 41 | Backup[ ]of[ ]*.numbers/ 42 | *.xcuserstate 43 | Sample Project/Sample Project.xcodeproj/xcuserdata 44 | Sample ARC/Sample ARC.xcodeproj/xcuserdata 45 | Sample Project/.idea 46 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * SFObservers http://merowing.info 3 | * 4 | * Copyright (c) 2012 Krzysztof Zabłocki 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ -------------------------------------------------------------------------------- /Sample ARC/Sample ARC/Sample ARC-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | pl.pixle.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Sample Project/Sample Project/Sample Project-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | pixle.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ### UPDATE: I'm no longer using SFObservers in any project, but will still accept pull requests for improvements. 3 | 4 | Purpose 5 | -------------- 6 | SFObservers is an category extension that adds auto removal for Observer pattern in NSNotificationCenter and KVO. 7 | 8 | By including this into your project, you no longer need to manually remove observers when observer object is deallocated. 9 | By default it also prevents adding more than once the same observer - parameters pair, it can be disabled by setting SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS to 1 in SFObservers.h 10 | 11 | [Follow me on twitter][1] 12 | 13 | Supported OS & SDK Versions 14 | ----------------------------- 15 | 16 | * iOS 4.0 (Xcode 4.3, Apple LLVM compiler 3.1) 17 | 18 | ARC Compatibility 19 | ------------------ 20 | 21 | SFObservers automatically works with both ARC and non-ARC projects through conditional compilation. There is no need to exclude SFObserver files from the ARC validation process, or to convert SFObservers using the ARC conversion tool. 22 | 23 | Installation 24 | -------------- 25 | 26 | To use the SFObserver in your app, just drag the class files (demo files and assets are not needed) into your project. And include SFObservers.h in your project Prefix.pch file. 27 | There is no need to call custom methods, you can include it into existing project and it will work fine. 28 | If you want to allow adding the same observer - parameters pairs, set SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS to 1 in SFObservers.h 29 | 30 | A [Cocoapods][2] spec is also available, just add this line to your Podfile: 31 | 32 | pod 'SFObservers', '~> 1.0' 33 | 34 | Tests 35 | -------------- 36 | 37 | Repository contains 2 sample projects with some unit tests, one is using ARC and other not. 38 | Also you can change SF_OBSERVERS_LOG_ORIGINAL_METHODS value to 1 if you would like to log original methods getting called. 39 | 40 | [1]: http://twitter.com/merowing_ 41 | [2]: http://cocoapods.org 42 | -------------------------------------------------------------------------------- /SFObservers/SFExecuteOnDealloc/NSObject+SFExecuteOnDealloc.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+SFExecuteOnDealloc.h 3 | // SampleProject 4 | // 5 | // Created by Krzysztof Zabłocki on 2/28/12. 6 | // Copyright (c) 2012 Krzysztof Zabłocki. All rights reserved. 7 | // 8 | 9 | // ARC Helper 10 | // 11 | // Version 1.2.2 12 | // 13 | // Created by Nick Lockwood on 05/01/2012. 14 | // Copyright 2012 Charcoal Design 15 | // 16 | // Distributed under the permissive zlib license 17 | // Get the latest version from here: 18 | // 19 | // https://gist.github.com/1563325 20 | 21 | // Krzysztof Zabłocki Added AH_BRIDGE(x) to bridge cast to void* 22 | #ifndef AH_RETAIN 23 | #if __has_feature(objc_arc) 24 | #define AH_RETAIN(x) (x) 25 | #define AH_RELEASE(x) (void)(x) 26 | #define AH_AUTORELEASE(x) (x) 27 | #define AH_SUPER_DEALLOC (void)(0) 28 | #define AH_BRIDGE(x) ((__bridge void*)x) 29 | #else 30 | #define __AH_WEAK 31 | #define AH_WEAK assign 32 | #define AH_RETAIN(x) [(x) retain] 33 | #define AH_RELEASE(x) [(x) release] 34 | #define AH_AUTORELEASE(x) [(x) autorelease] 35 | #define AH_SUPER_DEALLOC [super dealloc] 36 | #define AH_BRIDGE(x) (x) 37 | #endif 38 | #endif 39 | 40 | // Weak reference support 41 | 42 | #ifndef AH_WEAK 43 | #if defined __IPHONE_OS_VERSION_MIN_REQUIRED 44 | #if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_4_3 45 | #define __AH_WEAK __weak 46 | #define AH_WEAK weak 47 | #else 48 | #define __AH_WEAK __unsafe_unretained 49 | #define AH_WEAK unsafe_unretained 50 | #endif 51 | #elif defined __MAC_OS_X_VERSION_MIN_REQUIRED 52 | #if __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_6 53 | #define __AH_WEAK __weak 54 | #define AH_WEAK weak 55 | #else 56 | #define __AH_WEAK __unsafe_unretained 57 | #define AH_WEAK unsafe_unretained 58 | #endif 59 | #endif 60 | #endif 61 | 62 | #import 63 | 64 | 65 | #define SF_EXECUTE_ON_DEALLOC_USE_SHORTHAND 1 66 | 67 | @interface NSObject (SFExecuteOnDealloc) 68 | #if SF_EXECUTE_ON_DEALLOC_USE_SHORTHAND 69 | - (void *)performBlockOnDealloc:(void (^)(id))aBlock; 70 | 71 | - (void)cancelDeallocBlockWithKey:(void *)blockKey; 72 | #else 73 | - (void*)sf_performBlockOnDealloc:(void(^)(void))aBlock; 74 | - (void)sf_cancelDeallocBlockWithKey:(void*)blockKey; 75 | #endif 76 | @end 77 | -------------------------------------------------------------------------------- /SFObservers/SFExecuteOnDealloc/NSObject+SFExecuteOnDealloc.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+SFExecuteOnDealloc.m 3 | // SampleProject 4 | // 5 | // Created by Krzysztof Zabłocki on 2/28/12. 6 | // Copyright (c) 2012 Krzysztof Zabłocki. All rights reserved. 7 | // 8 | #import 9 | #import "NSObject+SFExecuteOnDealloc.h" 10 | #import "SFObservers.h" 11 | 12 | @interface SFExecuteOnDeallocInternalObject : NSObject 13 | @property(nonatomic, copy) void (^block)(id); 14 | @property(nonatomic, assign) __unsafe_unretained id obj; 15 | 16 | - (id)initWithBlock:(void (^)(id))aBlock; 17 | @end 18 | 19 | @implementation SFExecuteOnDeallocInternalObject { 20 | 21 | void(^block)(id); 22 | 23 | } 24 | @synthesize block; 25 | 26 | 27 | - (id)initWithBlock:(void (^)(id))aBlock 28 | { 29 | self = [super init]; 30 | if (self) { 31 | block = [aBlock copy]; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)dealloc 37 | { 38 | if (block) { 39 | block(_obj); 40 | AH_RELEASE(block); 41 | } 42 | AH_SUPER_DEALLOC; 43 | } 44 | @end 45 | 46 | @implementation NSObject (SFExecuteOnDealloc) 47 | #if SF_EXECUTE_ON_DEALLOC_USE_SHORTHAND 48 | - (void *)performBlockOnDealloc:(void (^)(id))aBlock 49 | #else 50 | - (void*)sf_performBlockOnDealloc:(void(^)(void))aBlock 51 | #endif 52 | { 53 | //! we need some object that will be deallocated with this one, and since we are only assigning and never again needing access to this object, let use its memory adress as key 54 | SFExecuteOnDeallocInternalObject *internalObject = [[SFExecuteOnDeallocInternalObject alloc] initWithBlock:aBlock]; 55 | internalObject.obj = self; 56 | objc_setAssociatedObject(self, AH_BRIDGE(internalObject), internalObject, OBJC_ASSOCIATION_RETAIN); 57 | AH_RELEASE(internalObject); 58 | return AH_BRIDGE(internalObject); 59 | } 60 | 61 | #if SF_EXECUTE_ON_DEALLOC_USE_SHORTHAND 62 | 63 | - (void)cancelDeallocBlockWithKey:(void *)blockKey 64 | #else 65 | - (void)sf_cancelDeallocBlockWithKey:(void*)blockKey 66 | #endif 67 | { 68 | //! first cleanup the associated block 69 | SFExecuteOnDeallocInternalObject *internalObject = objc_getAssociatedObject(self, blockKey); 70 | internalObject.block = nil; 71 | 72 | //! release internal object 73 | objc_setAssociatedObject(self, blockKey, nil, OBJC_ASSOCIATION_ASSIGN); 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARC/SFAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SFAppDelegate.m 3 | // Sample ARC 4 | // 5 | // Created by roche on 3/28/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "SFAppDelegate.h" 10 | 11 | @implementation SFAppDelegate 12 | 13 | @synthesize window = _window; 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | // Override point for customization after application launch. 19 | self.window.backgroundColor = [UIColor whiteColor]; 20 | [self.window makeKeyAndVisible]; 21 | return YES; 22 | } 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application 25 | { 26 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 27 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 28 | } 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application 31 | { 32 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 33 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 34 | } 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application 37 | { 38 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 39 | } 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application 42 | { 43 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 44 | } 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application 47 | { 48 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Sample Project/Sample Project/SFAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SFAppDelegate.m 3 | // Sample Project 4 | // 5 | // Created by Krzysztof Zablocki on 3/26/12. 6 | // Copyright (c) 2012 private. All rights reserved. 7 | // 8 | 9 | #import "SFAppDelegate.h" 10 | 11 | @implementation SFAppDelegate 12 | 13 | @synthesize window = _window; 14 | 15 | - (void)dealloc 16 | { 17 | [_window release]; 18 | [super dealloc]; 19 | } 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 24 | // Override point for customization after application launch. 25 | self.window.backgroundColor = [UIColor whiteColor]; 26 | [self.window makeKeyAndVisible]; 27 | return YES; 28 | } 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application 31 | { 32 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 33 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 34 | } 35 | 36 | - (void)applicationDidEnterBackground:(UIApplication *)application 37 | { 38 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | - (void)applicationWillEnterForeground:(UIApplication *)application 43 | { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | - (void)applicationDidBecomeActive:(UIApplication *)application 48 | { 49 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 50 | } 51 | 52 | - (void)applicationWillTerminate:(UIApplication *)application 53 | { 54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /SFObservers/SFObservers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SFObservers http://merowing.info 3 | * 4 | * Copyright (c) 2012 Krzysztof Zabłocki 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | // ARC Helper 27 | // 28 | // Version 1.2.2 29 | // 30 | // Created by Nick Lockwood on 05/01/2012. 31 | // Copyright 2012 Charcoal Design 32 | // 33 | // Distributed under the permissive zlib license 34 | // Get the latest version from here: 35 | // 36 | // https://gist.github.com/1563325 37 | 38 | // Krzysztof Zabłocki Added AH_BRIDGE(x) to bridge cast to void* 39 | 40 | #ifndef AH_RETAIN 41 | #if __has_feature(objc_arc) 42 | #define AH_RETAIN(x) (x) 43 | #define AH_RELEASE(x) (void)(x) 44 | #define AH_AUTORELEASE(x) (x) 45 | #define AH_SUPER_DEALLOC (void)(0) 46 | #define AH_BRIDGE(x) ((__bridge void*)x) 47 | #else 48 | #define __AH_WEAK 49 | #define AH_WEAK assign 50 | #define AH_RETAIN(x) [(x) retain] 51 | #define AH_RELEASE(x) [(x) release] 52 | #define AH_AUTORELEASE(x) [(x) autorelease] 53 | #define AH_SUPER_DEALLOC [super dealloc] 54 | #define AH_BRIDGE(x) (x) 55 | #endif 56 | #endif 57 | 58 | // Weak reference support 59 | 60 | #ifndef AH_WEAK 61 | #if defined __IPHONE_OS_VERSION_MIN_REQUIRED 62 | #if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_4_3 63 | #define __AH_WEAK __weak 64 | #define AH_WEAK weak 65 | #else 66 | #define __AH_WEAK __unsafe_unretained 67 | #define AH_WEAK unsafe_unretained 68 | #endif 69 | #elif defined __MAC_OS_X_VERSION_MIN_REQUIRED 70 | #if __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_6 71 | #define __AH_WEAK __weak 72 | #define AH_WEAK weak 73 | #else 74 | #define __AH_WEAK __unsafe_unretained 75 | #define AH_WEAK unsafe_unretained 76 | #endif 77 | #endif 78 | #endif 79 | 80 | #ifndef SF_OBSERVERS_LOG_ORIGINAL_METHODS 81 | #define SF_OBSERVERS_LOG_ORIGINAL_METHODS 0 82 | #endif 83 | 84 | #ifndef SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 85 | #define SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 1 86 | #endif 87 | 88 | #import "NSObject+SFExecuteOnDealloc.h" 89 | #import "NSNotificationCenter+SFObservers.h" 90 | #import "NSObject+SFObservers.h" 91 | -------------------------------------------------------------------------------- /SFObservers/NSObject+SFObservers.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by merowing2 on 3/25/12. 3 | // 4 | // 5 | // 6 | #import 7 | #import 8 | #import "NSObject+SFObservers.h" 9 | 10 | static NSString const *NSObjectKVOSFObserversArrayKey = @"NSObjectKVOSFObserversArrayKey"; 11 | static NSString const *NSObjectKVOSFObserversAllowMethodForwardingKey = @"NSObjectKVOSFObserversAllowMethodForwardingKey"; 12 | 13 | static NSString *NSObjectKVOSFObserversAddSelector = @"sf_original_addObserver:forKeyPath:options:context:"; 14 | static NSString *NSObjectKVOSFObserversRemoveSelector = @"sf_original_removeObserver:forKeyPath:"; 15 | static NSString *NSObjectKVOSFObserversRemoveSpecificSelector = @"sf_original_removeObserver:forKeyPath:context:"; 16 | 17 | @interface __SFObserversKVOObserverInfo : NSObject 18 | @property(nonatomic, copy) NSString *keyPath; 19 | @property(nonatomic, assign) void *context; 20 | @property(nonatomic, assign) void *blockKey; 21 | @end 22 | 23 | @implementation __SFObserversKVOObserverInfo 24 | @synthesize keyPath; 25 | @synthesize context; 26 | @synthesize blockKey; 27 | 28 | - (void)dealloc 29 | { 30 | AH_RELEASE(keyPath); 31 | AH_SUPER_DEALLOC; 32 | } 33 | 34 | @end 35 | 36 | 37 | @implementation NSObject (SFObservers) 38 | 39 | + (void)sf_swapSelector:(SEL)aOriginalSelector withSelector:(SEL)aSwappedSelector 40 | { 41 | Method originalMethod = class_getInstanceMethod(self, aOriginalSelector); 42 | Method swappedMethod = class_getInstanceMethod(self, aSwappedSelector); 43 | 44 | SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"sf_original_%@", NSStringFromSelector(aOriginalSelector)]); 45 | class_addMethod([self class], newSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 46 | class_replaceMethod([self class], aOriginalSelector, method_getImplementation(swappedMethod), method_getTypeEncoding(swappedMethod)); 47 | } 48 | 49 | + (void)load 50 | { 51 | //! swap methods 52 | static dispatch_once_t onceToken; 53 | dispatch_once(&onceToken, ^{ 54 | @autoreleasepool { 55 | [NSObject sf_swapSelector:@selector(addObserver:forKeyPath:options:context:) withSelector:@selector(sf_addObserver:forKeyPath:options:context:)]; 56 | [NSObject sf_swapSelector:@selector(removeObserver:forKeyPath:) withSelector:@selector(sf_removeObserver:forKeyPath:)]; 57 | [NSObject sf_swapSelector:@selector(removeObserver:forKeyPath:context:) withSelector:@selector(sf_removeObserver:forKeyPath:context:)]; 58 | } 59 | }); 60 | } 61 | 62 | - (BOOL)allowMethodForwarding 63 | { 64 | NSNumber *state = objc_getAssociatedObject(self, AH_BRIDGE(NSObjectKVOSFObserversAllowMethodForwardingKey)); 65 | return [state boolValue]; 66 | } 67 | 68 | - (void)setAllowMethodForwarding:(BOOL)allowForwarding 69 | { 70 | objc_setAssociatedObject(self, AH_BRIDGE(NSObjectKVOSFObserversAllowMethodForwardingKey), [NSNumber numberWithBool:allowForwarding], OBJC_ASSOCIATION_RETAIN); 71 | } 72 | 73 | - (void)sf_addObserver:(id)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)aContext 74 | { 75 | //! store info into our observer structure 76 | NSMutableDictionary *registeredKeyPaths = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSObjectKVOSFObserversArrayKey)); 77 | if (!registeredKeyPaths) { 78 | registeredKeyPaths = [NSMutableDictionary dictionary]; 79 | objc_setAssociatedObject(observer, AH_BRIDGE(NSObjectKVOSFObserversArrayKey), registeredKeyPaths, OBJC_ASSOCIATION_RETAIN); 80 | } 81 | 82 | NSMutableArray *observerInfos = [registeredKeyPaths objectForKey:keyPath]; 83 | if (!observerInfos) { 84 | observerInfos = [NSMutableArray array]; 85 | [registeredKeyPaths setObject:observerInfos forKey:keyPath]; 86 | } 87 | __block __SFObserversKVOObserverInfo *observerInfo = nil; 88 | 89 | #if !SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 90 | //! don't allow to add many times the same observer 91 | [observerInfos enumerateObjectsUsingBlock:^void(id obj, NSUInteger idx, BOOL *stop) { 92 | __SFObserversKVOObserverInfo *info = obj; 93 | if ([info.keyPath isEqualToString:keyPath] && info.context == aContext) { 94 | observerInfo = info; 95 | *stop = YES; 96 | } 97 | }]; 98 | 99 | if (!observerInfo) { 100 | observerInfo = [[__SFObserversKVOObserverInfo alloc] init]; 101 | [observerInfos addObject:observerInfo]; 102 | AH_RELEASE(observerInfo); 103 | } else { 104 | //! don't register twice so skip this 105 | NSAssert(NO, @"You shouldn't register twice for same keyPath, context"); 106 | return; 107 | } 108 | #else 109 | observerInfo = [[__SFObserversKVOObserverInfo alloc] init]; 110 | [observerInfos addObject:observerInfo]; 111 | AH_RELEASE(observerInfo); 112 | #endif 113 | 114 | observerInfo.keyPath = keyPath; 115 | observerInfo.context = aContext; 116 | 117 | //! Add auto remove when observer is going to be deallocated 118 | __AH_WEAK __block id weakSelf = self; 119 | 120 | void *key = [observer performBlockOnDealloc:^(id obj){ 121 | id strongObserver = obj; 122 | NSInteger numberOfRemovals = 0; 123 | if ((numberOfRemovals = [weakSelf sf_removeObserver:strongObserver forKeyPath:keyPath context:aContext registeredKeyPaths:registeredKeyPaths])) { 124 | for (NSInteger i = 0; i < numberOfRemovals; ++i) { 125 | [weakSelf setAllowMethodForwarding:YES]; 126 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 127 | NSLog(@"Calling original method %@ with parameters %@ %@ %p", NSObjectKVOSFObserversRemoveSpecificSelector, strongObserver, keyPath, aContext); 128 | #endif 129 | objc_msgSend(weakSelf, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), strongObserver, keyPath, aContext); 130 | [weakSelf setAllowMethodForwarding:NO]; 131 | } 132 | } 133 | }]; 134 | 135 | observerInfo.blockKey = key; 136 | 137 | //! call originalMethod 138 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 139 | NSLog(@"Calling original method %@ with parameters %@ %@ %d %p", NSObjectKVOSFObserversAddSelector, observer, keyPath, options, aContext); 140 | #endif 141 | objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversAddSelector), observer, keyPath, options, aContext); 142 | } 143 | 144 | 145 | - (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath 146 | { 147 | if ([self allowMethodForwarding]) { 148 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 149 | NSLog(@"Calling original method %@ with parameters %@ %@", NSObjectKVOSFObserversRemoveSelector, observer, keyPath); 150 | #endif 151 | objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversRemoveSelector), observer, keyPath); 152 | return; 153 | } 154 | 155 | NSMutableDictionary *registeredKeyPaths = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSObjectKVOSFObserversArrayKey)); 156 | NSInteger numberOfRemovals = 0; 157 | if ((numberOfRemovals = [self sf_removeObserver:observer forKeyPath:keyPath context:nil registeredKeyPaths:registeredKeyPaths])) { 158 | for (NSInteger i = 0; i < numberOfRemovals; ++i) { 159 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 160 | NSLog(@"Calling original method %@ with parameters %@ %@", NSObjectKVOSFObserversRemoveSelector, observer, keyPath); 161 | #endif 162 | [self setAllowMethodForwarding:YES]; 163 | objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversRemoveSelector), observer, keyPath); 164 | [self setAllowMethodForwarding:NO]; 165 | } 166 | } 167 | } 168 | 169 | - (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath context:(void *)context 170 | { 171 | if ([self allowMethodForwarding]) { 172 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 173 | NSLog(@"Calling original method %@ with parameters %@ %@ %p", NSObjectKVOSFObserversRemoveSpecificSelector, observer, keyPath, context); 174 | #endif 175 | objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), observer, keyPath, context); 176 | return; 177 | } 178 | 179 | NSMutableDictionary *registeredKeyPaths = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSObjectKVOSFObserversArrayKey)); 180 | NSInteger numberOfRemovals = 0; 181 | if ([self allowMethodForwarding] || (numberOfRemovals = [self sf_removeObserver:observer forKeyPath:keyPath context:context registeredKeyPaths:registeredKeyPaths])) { 182 | for (NSInteger i = 0; i < numberOfRemovals; ++i) { 183 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 184 | NSLog(@"Calling original method %@ with parameters %@ %@ %p", NSObjectKVOSFObserversRemoveSpecificSelector, observer, keyPath, context); 185 | #endif 186 | [self setAllowMethodForwarding:YES]; 187 | objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), observer, keyPath, context); 188 | [self setAllowMethodForwarding:NO]; 189 | } 190 | } 191 | 192 | } 193 | 194 | - (NSUInteger)sf_removeObserver:(id)observer 195 | forKeyPath:(NSString *)keyPath 196 | context:(void *)context 197 | registeredKeyPaths:(NSMutableDictionary *)registeredKeyPaths 198 | { 199 | __block NSUInteger result = 0; 200 | if ([keyPath length] <= 0 && context == nil) { 201 | //! don't need to execute block on dealloc so cleanup 202 | [registeredKeyPaths enumerateKeysAndObjectsUsingBlock:^void(id key, id obj, BOOL *stop) { 203 | NSMutableArray *observerInfos = obj; 204 | [observerInfos enumerateObjectsUsingBlock:^void(id innerObj, NSUInteger idx, BOOL *innerStop) { 205 | __SFObserversKVOObserverInfo *info = innerObj; 206 | [observer cancelDeallocBlockWithKey:info.blockKey]; 207 | }]; 208 | }]; 209 | [registeredKeyPaths removeAllObjects]; 210 | return 1; 211 | } else { 212 | [registeredKeyPaths enumerateKeysAndObjectsUsingBlock:^void(id key, id obj, BOOL *stop) { 213 | NSMutableArray *observerInfos = obj; 214 | NSMutableArray *objectsToRemove = [NSMutableArray array]; 215 | [observerInfos enumerateObjectsUsingBlock:^void(id innerObj, NSUInteger idx, BOOL *innerStop) { 216 | __SFObserversKVOObserverInfo *info = innerObj; 217 | 218 | if ((!keyPath || [keyPath isEqualToString:info.keyPath]) && (context == info.context)) { 219 | //! remove this info 220 | [objectsToRemove addObject:innerObj]; 221 | 222 | //! cancel dealloc block 223 | [observer cancelDeallocBlockWithKey:info.blockKey]; 224 | } 225 | }]; 226 | 227 | //! remove all collected objects 228 | if ([objectsToRemove count] > 0) { 229 | //! multiple registrations should match unregistrations 230 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 231 | result = [objectsToRemove count]; 232 | #else 233 | result = 1; 234 | #endif 235 | [observerInfos removeObjectsInArray:objectsToRemove]; 236 | } 237 | }]; 238 | } 239 | 240 | return result; 241 | } 242 | @end 243 | -------------------------------------------------------------------------------- /SFObservers/NSNotificationCenter+SFObservers.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by krzysztof.zablocki on 3/23/12. 3 | // 4 | // 5 | // 6 | 7 | #import "NSNotificationCenter+SFObservers.h" 8 | #import 9 | #import 10 | 11 | static NSString const *NSNotificationCenterSFObserversArrayKey = @"NSNotificationCenterSFObserversArrayKey"; 12 | static NSString const *NSNotificationCenterSFObserversAllowMethodForwardingKey = @"NSNotificationCenterSFObserversAllowMethodForwardingKey"; 13 | 14 | static NSString *NSNotificationCenterSFObserversAddSelector = @"sf_original_addObserver:selector:name:object:"; 15 | static NSString *NSNotificationCenterSFObserversRemoveSelector = @"sf_original_removeObserver:"; 16 | static NSString *NSNotificationCenterSFObserversRemoveSpecificSelector = @"sf_original_removeObserver:name:object:"; 17 | 18 | @interface __SFObserversNotificationObserverInfo : NSObject 19 | @property(nonatomic, copy) NSString *name; 20 | @property(nonatomic, AH_WEAK) id object; 21 | @property(nonatomic, assign) void *blockKey; 22 | @end 23 | 24 | @implementation __SFObserversNotificationObserverInfo 25 | @synthesize name; 26 | @synthesize object; 27 | @synthesize blockKey; 28 | 29 | 30 | - (void)dealloc 31 | { 32 | AH_RELEASE(name); 33 | AH_SUPER_DEALLOC; 34 | } 35 | 36 | @end 37 | 38 | @implementation NSNotificationCenter (SFObservers) 39 | 40 | + (void)sf_swapSelector:(SEL)aOriginalSelector withSelector:(SEL)aSwappedSelector 41 | { 42 | Method originalMethod = class_getInstanceMethod(self, aOriginalSelector); 43 | Method swappedMethod = class_getInstanceMethod(self, aSwappedSelector); 44 | 45 | SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"sf_original_%@", NSStringFromSelector(aOriginalSelector)]); 46 | class_addMethod([self class], newSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 47 | class_replaceMethod([self class], aOriginalSelector, method_getImplementation(swappedMethod), method_getTypeEncoding(swappedMethod)); 48 | } 49 | 50 | + (void)load 51 | { 52 | //! swap methods 53 | static dispatch_once_t onceToken; 54 | dispatch_once(&onceToken, ^{ 55 | @autoreleasepool { 56 | [NSNotificationCenter sf_swapSelector:@selector(addObserver:selector:name:object:) withSelector:@selector(sf_addObserver:selector:name:object:)]; 57 | [NSNotificationCenter sf_swapSelector:@selector(removeObserver:) withSelector:@selector(sf_removeObserver:)]; 58 | [NSNotificationCenter sf_swapSelector:@selector(removeObserver:name:object:) withSelector:@selector(sf_removeObserver:name:object:)]; 59 | } 60 | }); 61 | } 62 | 63 | - (BOOL)allowMethodForwarding 64 | { 65 | NSNumber *state = objc_getAssociatedObject(self, AH_BRIDGE(NSNotificationCenterSFObserversAllowMethodForwardingKey)); 66 | return [state boolValue]; 67 | } 68 | 69 | - (void)setAllowMethodForwarding:(BOOL)allowForwarding 70 | { 71 | objc_setAssociatedObject(self, AH_BRIDGE(NSNotificationCenterSFObserversAllowMethodForwardingKey), [NSNumber numberWithBool:allowForwarding], OBJC_ASSOCIATION_RETAIN); 72 | } 73 | 74 | - (void)sf_addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject 75 | { 76 | //! store info into our observer structure 77 | NSMutableDictionary *registeredNotifications = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSNotificationCenterSFObserversArrayKey)); 78 | if (!registeredNotifications) { 79 | registeredNotifications = [NSMutableDictionary dictionary]; 80 | objc_setAssociatedObject(observer, AH_BRIDGE(NSNotificationCenterSFObserversArrayKey), registeredNotifications, OBJC_ASSOCIATION_RETAIN); 81 | } 82 | 83 | NSMutableArray *observerInfos = [registeredNotifications objectForKey:NSStringFromSelector(aSelector)]; 84 | if (!observerInfos) { 85 | observerInfos = [NSMutableArray array]; 86 | [registeredNotifications setObject:observerInfos forKey:NSStringFromSelector(aSelector)]; 87 | } 88 | __block __SFObserversNotificationObserverInfo *observerInfo = nil; 89 | 90 | #if !SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 91 | //! don't allow to add many times the same observer 92 | [observerInfos enumerateObjectsUsingBlock:^void(id obj, NSUInteger idx, BOOL *stop) { 93 | __SFObserversNotificationObserverInfo *info = obj; 94 | if ([info.name isEqualToString:aName] && info.object == anObject) { 95 | observerInfo = info; 96 | *stop = YES; 97 | } 98 | }]; 99 | 100 | if (!observerInfo) { 101 | observerInfo = [[__SFObserversNotificationObserverInfo alloc] init]; 102 | [observerInfos addObject:observerInfo]; 103 | AH_RELEASE(observerInfo); 104 | } else { 105 | //! don't register twice so skip this 106 | NSAssert(NO, @"You shouldn't register twice for same notification, selector, name, object"); 107 | return; 108 | } 109 | #else 110 | observerInfo = [[__SFObserversNotificationObserverInfo alloc] init]; 111 | [observerInfos addObject:observerInfo]; 112 | AH_RELEASE(observerInfo); 113 | #endif 114 | 115 | observerInfo.name = aName; 116 | observerInfo.object = anObject; 117 | 118 | //! Add auto remove when observer is going to be deallocated 119 | __AH_WEAK __block id weakSelf = self; 120 | __AH_WEAK __block id weakObject = anObject; 121 | 122 | void *key = [observer performBlockOnDealloc:^(id obj){ 123 | id strongObserver = obj; 124 | NSInteger numberOfRemovals = 0; 125 | if ((numberOfRemovals = [weakSelf sf_removeObserver:strongObserver name:aName object:weakObject registeredNotifications:registeredNotifications])) { 126 | for (NSInteger i = 0; i < numberOfRemovals; ++i) { 127 | [weakSelf setAllowMethodForwarding:YES]; 128 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 129 | NSLog(@"Calling original method %@ with parameters %@ %@ %@", NSNotificationCenterSFObserversRemoveSpecificSelector, strongObserver, aName, weakObject); 130 | #endif 131 | objc_msgSend(weakSelf, NSSelectorFromString(NSNotificationCenterSFObserversRemoveSpecificSelector), strongObserver, aName, weakObject); 132 | [weakSelf setAllowMethodForwarding:NO]; 133 | } 134 | } 135 | }]; 136 | 137 | //! remember the block key 138 | observerInfo.blockKey = key; 139 | 140 | //! call originalMethod 141 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 142 | NSLog(@"Calling original method %@ with parameters %@ %@ %@ %@", NSNotificationCenterSFObserversAddSelector, observer, NSStringFromSelector(aSelector), aName, anObject); 143 | #endif 144 | objc_msgSend(self, NSSelectorFromString(NSNotificationCenterSFObserversAddSelector), observer, aSelector, aName, anObject); 145 | } 146 | 147 | 148 | - (void)sf_removeObserver:(id)observer 149 | { 150 | if ([self allowMethodForwarding]) { 151 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 152 | NSLog(@"Calling original method %@ with parameters %@", NSNotificationCenterSFObserversRemoveSelector, observer); 153 | #endif 154 | objc_msgSend(self, NSSelectorFromString(NSNotificationCenterSFObserversRemoveSelector), observer); 155 | return; 156 | } 157 | 158 | NSMutableDictionary *registeredNotifications = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSNotificationCenterSFObserversArrayKey)); 159 | NSInteger numberOfRemovals = 0; 160 | if ((numberOfRemovals = [self sf_removeObserver:observer name:nil object:nil registeredNotifications:registeredNotifications])) { 161 | for (NSInteger i = 0; i < numberOfRemovals; ++i) { 162 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 163 | NSLog(@"Calling original method %@ with parameters %@", NSNotificationCenterSFObserversRemoveSelector, observer); 164 | #endif 165 | [self setAllowMethodForwarding:YES]; 166 | objc_msgSend(self, NSSelectorFromString(NSNotificationCenterSFObserversRemoveSelector), observer); 167 | [self setAllowMethodForwarding:NO]; 168 | } 169 | } 170 | 171 | } 172 | 173 | - (void)sf_removeObserver:(id)observer name:(NSString *)aName object:(id)anObject 174 | { 175 | if ([self allowMethodForwarding]) { 176 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 177 | NSLog(@"Calling original method %@ with parameters %@ %@ %@", NSNotificationCenterSFObserversRemoveSpecificSelector, observer, aName, anObject); 178 | #endif 179 | objc_msgSend(self, NSSelectorFromString(NSNotificationCenterSFObserversRemoveSpecificSelector), observer, aName, anObject); 180 | return; 181 | } 182 | 183 | NSMutableDictionary *registeredNotifications = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSNotificationCenterSFObserversArrayKey)); 184 | NSInteger numberOfRemovals = 0; 185 | if ([self allowMethodForwarding] || (numberOfRemovals = [self sf_removeObserver:observer name:aName object:anObject registeredNotifications:registeredNotifications])) { 186 | [self setAllowMethodForwarding:YES]; 187 | #if SF_OBSERVERS_LOG_ORIGINAL_METHODS 188 | NSLog(@"Calling original method %@ with parameters %@ %@ %@", NSNotificationCenterSFObserversRemoveSpecificSelector, observer, aName, anObject); 189 | #endif 190 | objc_msgSend(self, NSSelectorFromString(NSNotificationCenterSFObserversRemoveSpecificSelector), observer, aName, anObject); 191 | [self setAllowMethodForwarding:NO]; 192 | } 193 | 194 | } 195 | 196 | - (NSUInteger)sf_removeObserver:(id)observer name:(NSString *)aName object:(id)anObject registeredNotifications:(NSMutableDictionary *)registeredNotifications 197 | { 198 | __block NSUInteger result = 0; 199 | 200 | if (aName == nil && anObject == nil) { 201 | //! don't need to execute block on dealloc so cleanup 202 | [registeredNotifications enumerateKeysAndObjectsUsingBlock:^void(id key, id obj, BOOL *stop) { 203 | NSMutableArray *observerInfos = obj; 204 | [observerInfos enumerateObjectsUsingBlock:^void(id innerObj, NSUInteger idx, BOOL *innerStop) { 205 | __SFObserversNotificationObserverInfo *info = innerObj; 206 | [observer cancelDeallocBlockWithKey:info.blockKey]; 207 | }]; 208 | }]; 209 | [registeredNotifications removeAllObjects]; 210 | 211 | return 1; 212 | } else { 213 | [registeredNotifications enumerateKeysAndObjectsUsingBlock:^void(id key, id obj, BOOL *stop) { 214 | NSMutableArray *observerInfos = obj; 215 | NSMutableArray *objectsToRemove = [NSMutableArray array]; 216 | [observerInfos enumerateObjectsUsingBlock:^void(id innerObj, NSUInteger idx, BOOL *innerStop) { 217 | __SFObserversNotificationObserverInfo *info = innerObj; 218 | 219 | if ((!aName || [aName isEqualToString:info.name]) && (!anObject || (anObject == info.object))) { 220 | //! remove this info 221 | [objectsToRemove addObject:innerObj]; 222 | 223 | //! cancel dealloc blocks 224 | [observer cancelDeallocBlockWithKey:info.blockKey]; 225 | } 226 | }]; 227 | 228 | //! remove all collected objects 229 | if ([objectsToRemove count] > 0) { 230 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 231 | result = [objectsToRemove count]; 232 | #else 233 | result = 1; 234 | #endif 235 | [observerInfos removeObjectsInArray:objectsToRemove]; 236 | } 237 | }]; 238 | } 239 | 240 | return result; 241 | } 242 | @end 243 | -------------------------------------------------------------------------------- /Sample Project/Sample ProjectTests/Sample_ProjectTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample_ProjectTests.m 3 | // Sample ProjectTests 4 | // 5 | // Created by Krzysztof Zablocki on 3/26/12. 6 | // Copyright (c) 2012 private. All rights reserved. 7 | // 8 | 9 | #import "Sample_ProjectTests.h" 10 | #import "SFObservers.h" 11 | 12 | @implementation Sample_ProjectTests { 13 | NSObject *observedObject; 14 | NSObject *observer; 15 | } 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | observedObject = [[NSObject alloc] init]; 22 | observer = [[NSObject alloc] init]; 23 | } 24 | 25 | - (void)tearDown 26 | { 27 | AH_RELEASE(observedObject); 28 | AH_RELEASE(observer); 29 | [super tearDown]; 30 | } 31 | 32 | - (void)testKVOAutoRemoval 33 | { 34 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:nil]; 35 | AH_RELEASE(observer), observer = nil; 36 | AH_RELEASE(observedObject), observedObject = nil; 37 | } 38 | 39 | - (void)testKVOAutoRemovalWithContext 40 | { 41 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 42 | AH_RELEASE(observer), observer = nil ; 43 | AH_RELEASE(observedObject), observedObject = nil; 44 | } 45 | 46 | - (void)testKVOAutoRemovalWithIntegerContext 47 | { 48 | static NSInteger SomeIntegerContext; 49 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:&SomeIntegerContext]; 50 | AH_RELEASE(observer), observer = nil; 51 | AH_RELEASE(observedObject), observedObject = nil; 52 | } 53 | 54 | - (void)testKVOAutoRemovalMultiple 55 | { 56 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 57 | [observedObject addObserver:observer forKeyPath:@"class" options:NSKeyValueObservingOptionNew context:nil]; 58 | [observedObject addObserver:observer forKeyPath:@"whatever" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 59 | AH_RELEASE(observer), observer = nil; 60 | AH_RELEASE(observedObject), observedObject = nil; 61 | } 62 | 63 | - (void)testKVOOverRemoval 64 | { 65 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 66 | [observedObject addObserver:observer forKeyPath:@"class" options:NSKeyValueObservingOptionNew context:nil]; 67 | [observedObject addObserver:observer forKeyPath:@"whatever" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 68 | 69 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 70 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 71 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 72 | 73 | AH_RELEASE(observer), observer = nil; 74 | AH_RELEASE(observedObject), observedObject = nil; 75 | } 76 | 77 | - (void)testKVOOverObserving 78 | { 79 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 80 | 81 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 82 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 83 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 84 | 85 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 86 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 87 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 88 | 89 | AH_RELEASE(observer), observer = nil; 90 | AH_RELEASE(observedObject), observedObject = nil; 91 | #endif 92 | } 93 | 94 | - (void)testKVOOverObserving2 95 | { 96 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 97 | 98 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 99 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 100 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 101 | 102 | AH_RELEASE(observer), observer = nil; 103 | AH_RELEASE(observedObject), observedObject = nil; 104 | #endif 105 | } 106 | 107 | - (void)testKVOOverObserving3 108 | { 109 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 110 | 111 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 112 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 113 | [observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)]; 114 | 115 | [observedObject removeObserver:observer forKeyPath:@"description" context:nil]; 116 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 117 | [observedObject removeObserver:observer forKeyPath:@"description" context:AH_BRIDGE(self)]; 118 | 119 | AH_RELEASE(observer), observer = nil; 120 | AH_RELEASE(observedObject), observedObject = nil; 121 | #endif 122 | } 123 | 124 | 125 | - (void)testKVONotBreakingArray 126 | { 127 | NSArray *array = [NSArray array]; 128 | STAssertThrows([array addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew context:nil], @"Array aren't observable, should raise exception"); 129 | } 130 | 131 | - (void)testNotificationAutoRemoval 132 | { 133 | @try { 134 | static NSString *fakeNotification = @"FakeNotification"; 135 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 136 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector2) name:fakeNotification object:nil]; 137 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector4) name:nil object:self]; 138 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector3) name:nil object:nil]; 139 | 140 | AH_RELEASE(observer), observer = nil; 141 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:self]; 142 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:nil]; 143 | [[NSNotificationCenter defaultCenter] postNotificationName:@"OtherNotification" object:self]; 144 | AH_RELEASE(observedObject), observedObject = nil; 145 | } 146 | @catch (NSException *exception1) { 147 | STFail(@"Exception %@", exception1); 148 | } 149 | } 150 | 151 | - (void)testNotificationOverRemoval 152 | { 153 | @try { 154 | static NSString *fakeNotification = @"FakeNotification"; 155 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 156 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector2) name:fakeNotification object:nil]; 157 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector4) name:nil object:self]; 158 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector3) name:nil object:nil]; 159 | 160 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:fakeNotification object:self]; 161 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:fakeNotification object:self]; 162 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:fakeNotification object:self]; 163 | 164 | AH_RELEASE(observer), observer = nil; 165 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:self]; 166 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:nil]; 167 | [[NSNotificationCenter defaultCenter] postNotificationName:@"OtherNotification" object:self]; 168 | AH_RELEASE(observedObject), observedObject = nil; 169 | } 170 | @catch (NSException *exception1) { 171 | STFail(@"Exception %@", exception1); 172 | } 173 | } 174 | 175 | - (void)testNotificationRemoval 176 | { 177 | @try { 178 | static NSString *fakeNotification = @"FakeNotification"; 179 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 180 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector2) name:fakeNotification object:nil]; 181 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector3) name:nil object:nil]; 182 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector4) name:nil object:self]; 183 | 184 | [[NSNotificationCenter defaultCenter] removeObserver:observer]; 185 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:self]; 186 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:nil]; 187 | [[NSNotificationCenter defaultCenter] postNotificationName:@"OtherNotification" object:self]; 188 | AH_RELEASE(observer), observer = nil; 189 | AH_RELEASE(observedObject), observedObject = nil; 190 | } 191 | @catch (NSException *exception1) { 192 | STFail(@"Exception %@", exception1); 193 | } 194 | } 195 | 196 | - (void)testNotificationOverObserving 197 | { 198 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 199 | 200 | @try { 201 | static NSString *fakeNotification = @"FakeNotification"; 202 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 203 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 204 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:nil object:nil]; 205 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:nil object:nil]; 206 | 207 | [[NSNotificationCenter defaultCenter] removeObserver:observer]; 208 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:self]; 209 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:nil]; 210 | [[NSNotificationCenter defaultCenter] postNotificationName:@"OtherNotification" object:self]; 211 | AH_RELEASE(observer), observer = nil; 212 | AH_RELEASE(observedObject), observedObject = nil; 213 | } 214 | @catch (NSException *exception1) { 215 | STFail(@"Exception %@", exception1); 216 | } 217 | #endif 218 | } 219 | 220 | - (void)testNotificationOverObserving2 221 | { 222 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 223 | 224 | @try { 225 | static NSString *fakeNotification = @"FakeNotification"; 226 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 227 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 228 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:nil object:nil]; 229 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:nil object:nil]; 230 | 231 | AH_RELEASE(observer), observer = nil; 232 | AH_RELEASE(observedObject), observedObject = nil; 233 | 234 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:self]; 235 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:nil]; 236 | [[NSNotificationCenter defaultCenter] postNotificationName:@"OtherNotification" object:self]; 237 | } 238 | @catch (NSException *exception1) { 239 | STFail(@"Exception %@", exception1); 240 | } 241 | #endif 242 | } 243 | 244 | - (void)testNotificationOverObserving3 245 | { 246 | #if SF_OBSERVERS_ALLOW_MULTIPLE_REGISTRATIONS 247 | 248 | @try { 249 | static NSString *fakeNotification = @"FakeNotification"; 250 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 251 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:fakeNotification object:self]; 252 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:nil object:nil]; 253 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(unsupportedSelector) name:nil object:nil]; 254 | 255 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:nil object:nil]; 256 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:fakeNotification object:nil]; 257 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:fakeNotification object:self]; 258 | 259 | AH_RELEASE(observer), observer = nil; 260 | AH_RELEASE(observedObject), observedObject = nil; 261 | 262 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:self]; 263 | [[NSNotificationCenter defaultCenter] postNotificationName:fakeNotification object:nil]; 264 | [[NSNotificationCenter defaultCenter] postNotificationName:@"OtherNotification" object:self]; 265 | } 266 | @catch (NSException *exception1) { 267 | STFail(@"Exception %@", exception1); 268 | } 269 | #endif 270 | } 271 | @end 272 | -------------------------------------------------------------------------------- /Sample Project/Sample Project.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D10828B91520FAD3008B8431 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10828B81520FAD3008B8431 /* UIKit.framework */; }; 11 | D10828BB1520FAD3008B8431 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10828BA1520FAD3008B8431 /* Foundation.framework */; }; 12 | D10828BD1520FAD3008B8431 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10828BC1520FAD3008B8431 /* CoreGraphics.framework */; }; 13 | D10828C31520FAD3008B8431 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D10828C11520FAD3008B8431 /* InfoPlist.strings */; }; 14 | D10828C51520FAD3008B8431 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D10828C41520FAD3008B8431 /* main.m */; }; 15 | D10828C91520FAD3008B8431 /* SFAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D10828C81520FAD3008B8431 /* SFAppDelegate.m */; }; 16 | D10828D11520FAD4008B8431 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10828D01520FAD4008B8431 /* SenTestingKit.framework */; }; 17 | D10828D21520FAD4008B8431 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10828B81520FAD3008B8431 /* UIKit.framework */; }; 18 | D10828D31520FAD4008B8431 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10828BA1520FAD3008B8431 /* Foundation.framework */; }; 19 | D10828DB1520FAD4008B8431 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D10828D91520FAD4008B8431 /* InfoPlist.strings */; }; 20 | D10828DE1520FAD4008B8431 /* Sample_ProjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D10828DD1520FAD4008B8431 /* Sample_ProjectTests.m */; }; 21 | D10828F01520FB32008B8431 /* NSNotificationCenter+SFObservers.m in Sources */ = {isa = PBXBuildFile; fileRef = D10828E91520FB32008B8431 /* NSNotificationCenter+SFObservers.m */; }; 22 | D10828F11520FB32008B8431 /* NSObject+SFObservers.m in Sources */ = {isa = PBXBuildFile; fileRef = D10828EB1520FB32008B8431 /* NSObject+SFObservers.m */; }; 23 | D10828F21520FB32008B8431 /* NSObject+SFExecuteOnDealloc.m in Sources */ = {isa = PBXBuildFile; fileRef = D10828EE1520FB32008B8431 /* NSObject+SFExecuteOnDealloc.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | D10828D41520FAD4008B8431 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = D10828AB1520FAD3008B8431 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = D10828B31520FAD3008B8431; 32 | remoteInfo = "Sample Project"; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | D10828B41520FAD3008B8431 /* Sample Project.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Sample Project.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | D10828B81520FAD3008B8431 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 39 | D10828BA1520FAD3008B8431 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 40 | D10828BC1520FAD3008B8431 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 41 | D10828C01520FAD3008B8431 /* Sample Project-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Sample Project-Info.plist"; sourceTree = ""; }; 42 | D10828C21520FAD3008B8431 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 43 | D10828C41520FAD3008B8431 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | D10828C61520FAD3008B8431 /* Sample Project-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Sample Project-Prefix.pch"; sourceTree = ""; }; 45 | D10828C71520FAD3008B8431 /* SFAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAppDelegate.h; sourceTree = ""; }; 46 | D10828C81520FAD3008B8431 /* SFAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAppDelegate.m; sourceTree = ""; }; 47 | D10828CF1520FAD4008B8431 /* Sample ProjectTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Sample ProjectTests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | D10828D01520FAD4008B8431 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 49 | D10828D81520FAD4008B8431 /* Sample ProjectTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Sample ProjectTests-Info.plist"; sourceTree = ""; }; 50 | D10828DA1520FAD4008B8431 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 51 | D10828DC1520FAD4008B8431 /* Sample_ProjectTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Sample_ProjectTests.h; sourceTree = ""; }; 52 | D10828DD1520FAD4008B8431 /* Sample_ProjectTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Sample_ProjectTests.m; sourceTree = ""; }; 53 | D10828E91520FB32008B8431 /* NSNotificationCenter+SFObservers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+SFObservers.m"; sourceTree = ""; }; 54 | D10828EA1520FB32008B8431 /* NSObject+SFObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SFObservers.h"; sourceTree = ""; }; 55 | D10828EB1520FB32008B8431 /* NSObject+SFObservers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SFObservers.m"; sourceTree = ""; }; 56 | D10828ED1520FB32008B8431 /* NSObject+SFExecuteOnDealloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SFExecuteOnDealloc.h"; sourceTree = ""; }; 57 | D10828EE1520FB32008B8431 /* NSObject+SFExecuteOnDealloc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SFExecuteOnDealloc.m"; sourceTree = ""; }; 58 | D10828EF1520FB32008B8431 /* SFObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFObservers.h; sourceTree = ""; }; 59 | FB8EDABC1523105000546E8E /* NSNotificationCenter+SFObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+SFObservers.h"; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | D10828B11520FAD3008B8431 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | D10828B91520FAD3008B8431 /* UIKit.framework in Frameworks */, 68 | D10828BB1520FAD3008B8431 /* Foundation.framework in Frameworks */, 69 | D10828BD1520FAD3008B8431 /* CoreGraphics.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | D10828CB1520FAD4008B8431 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | D10828D11520FAD4008B8431 /* SenTestingKit.framework in Frameworks */, 78 | D10828D21520FAD4008B8431 /* UIKit.framework in Frameworks */, 79 | D10828D31520FAD4008B8431 /* Foundation.framework in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | /* End PBXFrameworksBuildPhase section */ 84 | 85 | /* Begin PBXGroup section */ 86 | D10828A91520FAD3008B8431 = { 87 | isa = PBXGroup; 88 | children = ( 89 | D10828BE1520FAD3008B8431 /* Sample Project */, 90 | D10828D61520FAD4008B8431 /* Sample ProjectTests */, 91 | D10828B71520FAD3008B8431 /* Frameworks */, 92 | D10828B51520FAD3008B8431 /* Products */, 93 | ); 94 | sourceTree = ""; 95 | }; 96 | D10828B51520FAD3008B8431 /* Products */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | D10828B41520FAD3008B8431 /* Sample Project.app */, 100 | D10828CF1520FAD4008B8431 /* Sample ProjectTests.octest */, 101 | ); 102 | name = Products; 103 | sourceTree = ""; 104 | }; 105 | D10828B71520FAD3008B8431 /* Frameworks */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | D10828B81520FAD3008B8431 /* UIKit.framework */, 109 | D10828BA1520FAD3008B8431 /* Foundation.framework */, 110 | D10828BC1520FAD3008B8431 /* CoreGraphics.framework */, 111 | D10828D01520FAD4008B8431 /* SenTestingKit.framework */, 112 | ); 113 | name = Frameworks; 114 | sourceTree = ""; 115 | }; 116 | D10828BE1520FAD3008B8431 /* Sample Project */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | D10828E71520FB32008B8431 /* SFObservers */, 120 | D10828C71520FAD3008B8431 /* SFAppDelegate.h */, 121 | D10828C81520FAD3008B8431 /* SFAppDelegate.m */, 122 | D10828BF1520FAD3008B8431 /* Supporting Files */, 123 | ); 124 | path = "Sample Project"; 125 | sourceTree = ""; 126 | }; 127 | D10828BF1520FAD3008B8431 /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | D10828C01520FAD3008B8431 /* Sample Project-Info.plist */, 131 | D10828C11520FAD3008B8431 /* InfoPlist.strings */, 132 | D10828C41520FAD3008B8431 /* main.m */, 133 | D10828C61520FAD3008B8431 /* Sample Project-Prefix.pch */, 134 | ); 135 | name = "Supporting Files"; 136 | sourceTree = ""; 137 | }; 138 | D10828D61520FAD4008B8431 /* Sample ProjectTests */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | D10828DC1520FAD4008B8431 /* Sample_ProjectTests.h */, 142 | D10828DD1520FAD4008B8431 /* Sample_ProjectTests.m */, 143 | D10828D71520FAD4008B8431 /* Supporting Files */, 144 | ); 145 | path = "Sample ProjectTests"; 146 | sourceTree = ""; 147 | }; 148 | D10828D71520FAD4008B8431 /* Supporting Files */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | D10828D81520FAD4008B8431 /* Sample ProjectTests-Info.plist */, 152 | D10828D91520FAD4008B8431 /* InfoPlist.strings */, 153 | ); 154 | name = "Supporting Files"; 155 | sourceTree = ""; 156 | }; 157 | D10828E71520FB32008B8431 /* SFObservers */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | D10828EC1520FB32008B8431 /* SFExecuteOnDealloc */, 161 | FB8EDABC1523105000546E8E /* NSNotificationCenter+SFObservers.h */, 162 | D10828E91520FB32008B8431 /* NSNotificationCenter+SFObservers.m */, 163 | D10828EA1520FB32008B8431 /* NSObject+SFObservers.h */, 164 | D10828EB1520FB32008B8431 /* NSObject+SFObservers.m */, 165 | D10828EF1520FB32008B8431 /* SFObservers.h */, 166 | ); 167 | name = SFObservers; 168 | path = ../../SFObservers; 169 | sourceTree = ""; 170 | }; 171 | D10828EC1520FB32008B8431 /* SFExecuteOnDealloc */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | D10828ED1520FB32008B8431 /* NSObject+SFExecuteOnDealloc.h */, 175 | D10828EE1520FB32008B8431 /* NSObject+SFExecuteOnDealloc.m */, 176 | ); 177 | path = SFExecuteOnDealloc; 178 | sourceTree = ""; 179 | }; 180 | /* End PBXGroup section */ 181 | 182 | /* Begin PBXNativeTarget section */ 183 | D10828B31520FAD3008B8431 /* Sample Project */ = { 184 | isa = PBXNativeTarget; 185 | buildConfigurationList = D10828E11520FAD4008B8431 /* Build configuration list for PBXNativeTarget "Sample Project" */; 186 | buildPhases = ( 187 | D10828B01520FAD3008B8431 /* Sources */, 188 | D10828B11520FAD3008B8431 /* Frameworks */, 189 | D10828B21520FAD3008B8431 /* Resources */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | ); 195 | name = "Sample Project"; 196 | productName = "Sample Project"; 197 | productReference = D10828B41520FAD3008B8431 /* Sample Project.app */; 198 | productType = "com.apple.product-type.application"; 199 | }; 200 | D10828CE1520FAD4008B8431 /* Sample ProjectTests */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = D10828E41520FAD4008B8431 /* Build configuration list for PBXNativeTarget "Sample ProjectTests" */; 203 | buildPhases = ( 204 | D10828CA1520FAD4008B8431 /* Sources */, 205 | D10828CB1520FAD4008B8431 /* Frameworks */, 206 | D10828CC1520FAD4008B8431 /* Resources */, 207 | D10828CD1520FAD4008B8431 /* ShellScript */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | D10828D51520FAD4008B8431 /* PBXTargetDependency */, 213 | ); 214 | name = "Sample ProjectTests"; 215 | productName = "Sample ProjectTests"; 216 | productReference = D10828CF1520FAD4008B8431 /* Sample ProjectTests.octest */; 217 | productType = "com.apple.product-type.bundle"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | D10828AB1520FAD3008B8431 /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | CLASSPREFIX = SF; 226 | LastUpgradeCheck = 0430; 227 | ORGANIZATIONNAME = private; 228 | }; 229 | buildConfigurationList = D10828AE1520FAD3008B8431 /* Build configuration list for PBXProject "Sample Project" */; 230 | compatibilityVersion = "Xcode 3.2"; 231 | developmentRegion = English; 232 | hasScannedForEncodings = 0; 233 | knownRegions = ( 234 | en, 235 | ); 236 | mainGroup = D10828A91520FAD3008B8431; 237 | productRefGroup = D10828B51520FAD3008B8431 /* Products */; 238 | projectDirPath = ""; 239 | projectRoot = ""; 240 | targets = ( 241 | D10828B31520FAD3008B8431 /* Sample Project */, 242 | D10828CE1520FAD4008B8431 /* Sample ProjectTests */, 243 | ); 244 | }; 245 | /* End PBXProject section */ 246 | 247 | /* Begin PBXResourcesBuildPhase section */ 248 | D10828B21520FAD3008B8431 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | D10828C31520FAD3008B8431 /* InfoPlist.strings in Resources */, 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | }; 256 | D10828CC1520FAD4008B8431 /* Resources */ = { 257 | isa = PBXResourcesBuildPhase; 258 | buildActionMask = 2147483647; 259 | files = ( 260 | D10828DB1520FAD4008B8431 /* InfoPlist.strings in Resources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXResourcesBuildPhase section */ 265 | 266 | /* Begin PBXShellScriptBuildPhase section */ 267 | D10828CD1520FAD4008B8431 /* ShellScript */ = { 268 | isa = PBXShellScriptBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | ); 272 | inputPaths = ( 273 | ); 274 | outputPaths = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 279 | }; 280 | /* End PBXShellScriptBuildPhase section */ 281 | 282 | /* Begin PBXSourcesBuildPhase section */ 283 | D10828B01520FAD3008B8431 /* Sources */ = { 284 | isa = PBXSourcesBuildPhase; 285 | buildActionMask = 2147483647; 286 | files = ( 287 | D10828C51520FAD3008B8431 /* main.m in Sources */, 288 | D10828C91520FAD3008B8431 /* SFAppDelegate.m in Sources */, 289 | D10828F01520FB32008B8431 /* NSNotificationCenter+SFObservers.m in Sources */, 290 | D10828F11520FB32008B8431 /* NSObject+SFObservers.m in Sources */, 291 | D10828F21520FB32008B8431 /* NSObject+SFExecuteOnDealloc.m in Sources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | D10828CA1520FAD4008B8431 /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | D10828DE1520FAD4008B8431 /* Sample_ProjectTests.m in Sources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | /* End PBXSourcesBuildPhase section */ 304 | 305 | /* Begin PBXTargetDependency section */ 306 | D10828D51520FAD4008B8431 /* PBXTargetDependency */ = { 307 | isa = PBXTargetDependency; 308 | target = D10828B31520FAD3008B8431 /* Sample Project */; 309 | targetProxy = D10828D41520FAD4008B8431 /* PBXContainerItemProxy */; 310 | }; 311 | /* End PBXTargetDependency section */ 312 | 313 | /* Begin PBXVariantGroup section */ 314 | D10828C11520FAD3008B8431 /* InfoPlist.strings */ = { 315 | isa = PBXVariantGroup; 316 | children = ( 317 | D10828C21520FAD3008B8431 /* en */, 318 | ); 319 | name = InfoPlist.strings; 320 | sourceTree = ""; 321 | }; 322 | D10828D91520FAD4008B8431 /* InfoPlist.strings */ = { 323 | isa = PBXVariantGroup; 324 | children = ( 325 | D10828DA1520FAD4008B8431 /* en */, 326 | ); 327 | name = InfoPlist.strings; 328 | sourceTree = ""; 329 | }; 330 | /* End PBXVariantGroup section */ 331 | 332 | /* Begin XCBuildConfiguration section */ 333 | D10828DF1520FAD4008B8431 /* Debug */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ALWAYS_SEARCH_USER_PATHS = NO; 337 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | COPY_PHASE_STRIP = NO; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_DYNAMIC_NO_PIC = NO; 342 | GCC_OPTIMIZATION_LEVEL = 0; 343 | GCC_PREPROCESSOR_DEFINITIONS = ( 344 | "DEBUG=1", 345 | "$(inherited)", 346 | ); 347 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 348 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 349 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 350 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 351 | GCC_WARN_UNUSED_VARIABLE = YES; 352 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 353 | SDKROOT = iphoneos; 354 | TARGETED_DEVICE_FAMILY = "1,2"; 355 | }; 356 | name = Debug; 357 | }; 358 | D10828E01520FAD4008B8431 /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ALWAYS_SEARCH_USER_PATHS = NO; 362 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 363 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 364 | COPY_PHASE_STRIP = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 367 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 368 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 371 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 372 | SDKROOT = iphoneos; 373 | TARGETED_DEVICE_FAMILY = "1,2"; 374 | VALIDATE_PRODUCT = YES; 375 | }; 376 | name = Release; 377 | }; 378 | D10828E21520FAD4008B8431 /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 382 | GCC_PREFIX_HEADER = "Sample Project/Sample Project-Prefix.pch"; 383 | INFOPLIST_FILE = "Sample Project/Sample Project-Info.plist"; 384 | PRODUCT_NAME = "$(TARGET_NAME)"; 385 | WRAPPER_EXTENSION = app; 386 | }; 387 | name = Debug; 388 | }; 389 | D10828E31520FAD4008B8431 /* Release */ = { 390 | isa = XCBuildConfiguration; 391 | buildSettings = { 392 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 393 | GCC_PREFIX_HEADER = "Sample Project/Sample Project-Prefix.pch"; 394 | INFOPLIST_FILE = "Sample Project/Sample Project-Info.plist"; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | WRAPPER_EXTENSION = app; 397 | }; 398 | name = Release; 399 | }; 400 | D10828E51520FAD4008B8431 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Sample Project.app/Sample Project"; 404 | FRAMEWORK_SEARCH_PATHS = ( 405 | "$(SDKROOT)/Developer/Library/Frameworks", 406 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 407 | ); 408 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 409 | GCC_PREFIX_HEADER = "Sample Project/Sample Project-Prefix.pch"; 410 | INFOPLIST_FILE = "Sample ProjectTests/Sample ProjectTests-Info.plist"; 411 | PRODUCT_NAME = "$(TARGET_NAME)"; 412 | TEST_HOST = "$(BUNDLE_LOADER)"; 413 | WRAPPER_EXTENSION = octest; 414 | }; 415 | name = Debug; 416 | }; 417 | D10828E61520FAD4008B8431 /* Release */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Sample Project.app/Sample Project"; 421 | FRAMEWORK_SEARCH_PATHS = ( 422 | "$(SDKROOT)/Developer/Library/Frameworks", 423 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 424 | ); 425 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 426 | GCC_PREFIX_HEADER = "Sample Project/Sample Project-Prefix.pch"; 427 | INFOPLIST_FILE = "Sample ProjectTests/Sample ProjectTests-Info.plist"; 428 | PRODUCT_NAME = "$(TARGET_NAME)"; 429 | TEST_HOST = "$(BUNDLE_LOADER)"; 430 | WRAPPER_EXTENSION = octest; 431 | }; 432 | name = Release; 433 | }; 434 | /* End XCBuildConfiguration section */ 435 | 436 | /* Begin XCConfigurationList section */ 437 | D10828AE1520FAD3008B8431 /* Build configuration list for PBXProject "Sample Project" */ = { 438 | isa = XCConfigurationList; 439 | buildConfigurations = ( 440 | D10828DF1520FAD4008B8431 /* Debug */, 441 | D10828E01520FAD4008B8431 /* Release */, 442 | ); 443 | defaultConfigurationIsVisible = 0; 444 | defaultConfigurationName = Release; 445 | }; 446 | D10828E11520FAD4008B8431 /* Build configuration list for PBXNativeTarget "Sample Project" */ = { 447 | isa = XCConfigurationList; 448 | buildConfigurations = ( 449 | D10828E21520FAD4008B8431 /* Debug */, 450 | D10828E31520FAD4008B8431 /* Release */, 451 | ); 452 | defaultConfigurationIsVisible = 0; 453 | defaultConfigurationName = Release; 454 | }; 455 | D10828E41520FAD4008B8431 /* Build configuration list for PBXNativeTarget "Sample ProjectTests" */ = { 456 | isa = XCConfigurationList; 457 | buildConfigurations = ( 458 | D10828E51520FAD4008B8431 /* Debug */, 459 | D10828E61520FAD4008B8431 /* Release */, 460 | ); 461 | defaultConfigurationIsVisible = 0; 462 | defaultConfigurationName = Release; 463 | }; 464 | /* End XCConfigurationList section */ 465 | }; 466 | rootObject = D10828AB1520FAD3008B8431 /* Project object */; 467 | } 468 | -------------------------------------------------------------------------------- /Sample ARC/Sample ARC.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FB8EDACD152310F200546E8E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB8EDACC152310F200546E8E /* UIKit.framework */; }; 11 | FB8EDACF152310F200546E8E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB8EDACE152310F200546E8E /* Foundation.framework */; }; 12 | FB8EDAD1152310F200546E8E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB8EDAD0152310F200546E8E /* CoreGraphics.framework */; }; 13 | FB8EDAD7152310F200546E8E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FB8EDAD5152310F200546E8E /* InfoPlist.strings */; }; 14 | FB8EDAD9152310F200546E8E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDAD8152310F200546E8E /* main.m */; }; 15 | FB8EDADD152310F200546E8E /* SFAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDADC152310F200546E8E /* SFAppDelegate.m */; }; 16 | FB8EDAE5152310F300546E8E /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB8EDAE4152310F200546E8E /* SenTestingKit.framework */; }; 17 | FB8EDAE6152310F300546E8E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB8EDACC152310F200546E8E /* UIKit.framework */; }; 18 | FB8EDAE7152310F300546E8E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB8EDACE152310F200546E8E /* Foundation.framework */; }; 19 | FB8EDAEF152310F300546E8E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FB8EDAED152310F300546E8E /* InfoPlist.strings */; }; 20 | FB8EDAF2152310F300546E8E /* Sample_ARCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDAF1152310F300546E8E /* Sample_ARCTests.m */; }; 21 | FB8EDAFD1523111B00546E8E /* Sample_ProjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDAFC1523111B00546E8E /* Sample_ProjectTests.m */; }; 22 | FB8EDB071523112800546E8E /* NSNotificationCenter+SFObservers.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDB001523112800546E8E /* NSNotificationCenter+SFObservers.m */; }; 23 | FB8EDB081523112800546E8E /* NSObject+SFObservers.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDB021523112800546E8E /* NSObject+SFObservers.m */; }; 24 | FB8EDB091523112800546E8E /* NSObject+SFExecuteOnDealloc.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8EDB051523112800546E8E /* NSObject+SFExecuteOnDealloc.m */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | FB8EDAE8152310F300546E8E /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = FB8EDABF152310F100546E8E /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = FB8EDAC7152310F200546E8E; 33 | remoteInfo = "Sample ARC"; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | FB8EDAC8152310F200546E8E /* Sample ARC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Sample ARC.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | FB8EDACC152310F200546E8E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 40 | FB8EDACE152310F200546E8E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 41 | FB8EDAD0152310F200546E8E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 42 | FB8EDAD4152310F200546E8E /* Sample ARC-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Sample ARC-Info.plist"; sourceTree = ""; }; 43 | FB8EDAD6152310F200546E8E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 44 | FB8EDAD8152310F200546E8E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | FB8EDADA152310F200546E8E /* Sample ARC-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Sample ARC-Prefix.pch"; sourceTree = ""; }; 46 | FB8EDADB152310F200546E8E /* SFAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAppDelegate.h; sourceTree = ""; }; 47 | FB8EDADC152310F200546E8E /* SFAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAppDelegate.m; sourceTree = ""; }; 48 | FB8EDAE3152310F200546E8E /* Sample ARCTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Sample ARCTests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | FB8EDAE4152310F200546E8E /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 50 | FB8EDAEC152310F300546E8E /* Sample ARCTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Sample ARCTests-Info.plist"; sourceTree = ""; }; 51 | FB8EDAEE152310F300546E8E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 52 | FB8EDAF0152310F300546E8E /* Sample_ARCTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Sample_ARCTests.h; sourceTree = ""; }; 53 | FB8EDAF1152310F300546E8E /* Sample_ARCTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Sample_ARCTests.m; sourceTree = ""; }; 54 | FB8EDAFB1523111B00546E8E /* Sample_ProjectTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sample_ProjectTests.h; path = "../../Sample Project/Sample ProjectTests/Sample_ProjectTests.h"; sourceTree = ""; }; 55 | FB8EDAFC1523111B00546E8E /* Sample_ProjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Sample_ProjectTests.m; path = "../../Sample Project/Sample ProjectTests/Sample_ProjectTests.m"; sourceTree = ""; }; 56 | FB8EDAFF1523112800546E8E /* NSNotificationCenter+SFObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+SFObservers.h"; sourceTree = ""; }; 57 | FB8EDB001523112800546E8E /* NSNotificationCenter+SFObservers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+SFObservers.m"; sourceTree = ""; }; 58 | FB8EDB011523112800546E8E /* NSObject+SFObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SFObservers.h"; sourceTree = ""; }; 59 | FB8EDB021523112800546E8E /* NSObject+SFObservers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SFObservers.m"; sourceTree = ""; }; 60 | FB8EDB041523112800546E8E /* NSObject+SFExecuteOnDealloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SFExecuteOnDealloc.h"; sourceTree = ""; }; 61 | FB8EDB051523112800546E8E /* NSObject+SFExecuteOnDealloc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SFExecuteOnDealloc.m"; sourceTree = ""; }; 62 | FB8EDB061523112800546E8E /* SFObservers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFObservers.h; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | FB8EDAC5152310F200546E8E /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | FB8EDACD152310F200546E8E /* UIKit.framework in Frameworks */, 71 | FB8EDACF152310F200546E8E /* Foundation.framework in Frameworks */, 72 | FB8EDAD1152310F200546E8E /* CoreGraphics.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | FB8EDADF152310F200546E8E /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | FB8EDAE5152310F300546E8E /* SenTestingKit.framework in Frameworks */, 81 | FB8EDAE6152310F300546E8E /* UIKit.framework in Frameworks */, 82 | FB8EDAE7152310F300546E8E /* Foundation.framework in Frameworks */, 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXFrameworksBuildPhase section */ 87 | 88 | /* Begin PBXGroup section */ 89 | FB8EDABD152310F100546E8E = { 90 | isa = PBXGroup; 91 | children = ( 92 | FB8EDAD2152310F200546E8E /* Sample ARC */, 93 | FB8EDAEA152310F300546E8E /* Sample ARCTests */, 94 | FB8EDACB152310F200546E8E /* Frameworks */, 95 | FB8EDAC9152310F200546E8E /* Products */, 96 | ); 97 | sourceTree = ""; 98 | }; 99 | FB8EDAC9152310F200546E8E /* Products */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | FB8EDAC8152310F200546E8E /* Sample ARC.app */, 103 | FB8EDAE3152310F200546E8E /* Sample ARCTests.octest */, 104 | ); 105 | name = Products; 106 | sourceTree = ""; 107 | }; 108 | FB8EDACB152310F200546E8E /* Frameworks */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | FB8EDACC152310F200546E8E /* UIKit.framework */, 112 | FB8EDACE152310F200546E8E /* Foundation.framework */, 113 | FB8EDAD0152310F200546E8E /* CoreGraphics.framework */, 114 | FB8EDAE4152310F200546E8E /* SenTestingKit.framework */, 115 | ); 116 | name = Frameworks; 117 | sourceTree = ""; 118 | }; 119 | FB8EDAD2152310F200546E8E /* Sample ARC */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | FB8EDAFE1523112800546E8E /* SFObservers */, 123 | FB8EDADB152310F200546E8E /* SFAppDelegate.h */, 124 | FB8EDADC152310F200546E8E /* SFAppDelegate.m */, 125 | FB8EDAD3152310F200546E8E /* Supporting Files */, 126 | ); 127 | path = "Sample ARC"; 128 | sourceTree = ""; 129 | }; 130 | FB8EDAD3152310F200546E8E /* Supporting Files */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | FB8EDAD4152310F200546E8E /* Sample ARC-Info.plist */, 134 | FB8EDAD5152310F200546E8E /* InfoPlist.strings */, 135 | FB8EDAD8152310F200546E8E /* main.m */, 136 | FB8EDADA152310F200546E8E /* Sample ARC-Prefix.pch */, 137 | ); 138 | name = "Supporting Files"; 139 | sourceTree = ""; 140 | }; 141 | FB8EDAEA152310F300546E8E /* Sample ARCTests */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | FB8EDAFB1523111B00546E8E /* Sample_ProjectTests.h */, 145 | FB8EDAFC1523111B00546E8E /* Sample_ProjectTests.m */, 146 | FB8EDAF0152310F300546E8E /* Sample_ARCTests.h */, 147 | FB8EDAF1152310F300546E8E /* Sample_ARCTests.m */, 148 | FB8EDAEB152310F300546E8E /* Supporting Files */, 149 | ); 150 | path = "Sample ARCTests"; 151 | sourceTree = ""; 152 | }; 153 | FB8EDAEB152310F300546E8E /* Supporting Files */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | FB8EDAEC152310F300546E8E /* Sample ARCTests-Info.plist */, 157 | FB8EDAED152310F300546E8E /* InfoPlist.strings */, 158 | ); 159 | name = "Supporting Files"; 160 | sourceTree = ""; 161 | }; 162 | FB8EDAFE1523112800546E8E /* SFObservers */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | FB8EDB031523112800546E8E /* SFExecuteOnDealloc */, 166 | FB8EDAFF1523112800546E8E /* NSNotificationCenter+SFObservers.h */, 167 | FB8EDB001523112800546E8E /* NSNotificationCenter+SFObservers.m */, 168 | FB8EDB011523112800546E8E /* NSObject+SFObservers.h */, 169 | FB8EDB021523112800546E8E /* NSObject+SFObservers.m */, 170 | FB8EDB061523112800546E8E /* SFObservers.h */, 171 | ); 172 | name = SFObservers; 173 | path = ../../SFObservers; 174 | sourceTree = ""; 175 | }; 176 | FB8EDB031523112800546E8E /* SFExecuteOnDealloc */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | FB8EDB041523112800546E8E /* NSObject+SFExecuteOnDealloc.h */, 180 | FB8EDB051523112800546E8E /* NSObject+SFExecuteOnDealloc.m */, 181 | ); 182 | path = SFExecuteOnDealloc; 183 | sourceTree = ""; 184 | }; 185 | /* End PBXGroup section */ 186 | 187 | /* Begin PBXNativeTarget section */ 188 | FB8EDAC7152310F200546E8E /* Sample ARC */ = { 189 | isa = PBXNativeTarget; 190 | buildConfigurationList = FB8EDAF5152310F300546E8E /* Build configuration list for PBXNativeTarget "Sample ARC" */; 191 | buildPhases = ( 192 | FB8EDAC4152310F200546E8E /* Sources */, 193 | FB8EDAC5152310F200546E8E /* Frameworks */, 194 | FB8EDAC6152310F200546E8E /* Resources */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | ); 200 | name = "Sample ARC"; 201 | productName = "Sample ARC"; 202 | productReference = FB8EDAC8152310F200546E8E /* Sample ARC.app */; 203 | productType = "com.apple.product-type.application"; 204 | }; 205 | FB8EDAE2152310F200546E8E /* Sample ARCTests */ = { 206 | isa = PBXNativeTarget; 207 | buildConfigurationList = FB8EDAF8152310F300546E8E /* Build configuration list for PBXNativeTarget "Sample ARCTests" */; 208 | buildPhases = ( 209 | FB8EDADE152310F200546E8E /* Sources */, 210 | FB8EDADF152310F200546E8E /* Frameworks */, 211 | FB8EDAE0152310F200546E8E /* Resources */, 212 | FB8EDAE1152310F200546E8E /* ShellScript */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | FB8EDAE9152310F300546E8E /* PBXTargetDependency */, 218 | ); 219 | name = "Sample ARCTests"; 220 | productName = "Sample ARCTests"; 221 | productReference = FB8EDAE3152310F200546E8E /* Sample ARCTests.octest */; 222 | productType = "com.apple.product-type.bundle"; 223 | }; 224 | /* End PBXNativeTarget section */ 225 | 226 | /* Begin PBXProject section */ 227 | FB8EDABF152310F100546E8E /* Project object */ = { 228 | isa = PBXProject; 229 | attributes = { 230 | CLASSPREFIX = SF; 231 | LastUpgradeCheck = 0430; 232 | }; 233 | buildConfigurationList = FB8EDAC2152310F100546E8E /* Build configuration list for PBXProject "Sample ARC" */; 234 | compatibilityVersion = "Xcode 3.2"; 235 | developmentRegion = English; 236 | hasScannedForEncodings = 0; 237 | knownRegions = ( 238 | en, 239 | ); 240 | mainGroup = FB8EDABD152310F100546E8E; 241 | productRefGroup = FB8EDAC9152310F200546E8E /* Products */; 242 | projectDirPath = ""; 243 | projectRoot = ""; 244 | targets = ( 245 | FB8EDAC7152310F200546E8E /* Sample ARC */, 246 | FB8EDAE2152310F200546E8E /* Sample ARCTests */, 247 | ); 248 | }; 249 | /* End PBXProject section */ 250 | 251 | /* Begin PBXResourcesBuildPhase section */ 252 | FB8EDAC6152310F200546E8E /* Resources */ = { 253 | isa = PBXResourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | FB8EDAD7152310F200546E8E /* InfoPlist.strings in Resources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | FB8EDAE0152310F200546E8E /* Resources */ = { 261 | isa = PBXResourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | FB8EDAEF152310F300546E8E /* InfoPlist.strings in Resources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | /* End PBXResourcesBuildPhase section */ 269 | 270 | /* Begin PBXShellScriptBuildPhase section */ 271 | FB8EDAE1152310F200546E8E /* ShellScript */ = { 272 | isa = PBXShellScriptBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | ); 276 | inputPaths = ( 277 | ); 278 | outputPaths = ( 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | shellPath = /bin/sh; 282 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 283 | }; 284 | /* End PBXShellScriptBuildPhase section */ 285 | 286 | /* Begin PBXSourcesBuildPhase section */ 287 | FB8EDAC4152310F200546E8E /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | FB8EDAD9152310F200546E8E /* main.m in Sources */, 292 | FB8EDADD152310F200546E8E /* SFAppDelegate.m in Sources */, 293 | FB8EDB071523112800546E8E /* NSNotificationCenter+SFObservers.m in Sources */, 294 | FB8EDB081523112800546E8E /* NSObject+SFObservers.m in Sources */, 295 | FB8EDB091523112800546E8E /* NSObject+SFExecuteOnDealloc.m in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | FB8EDADE152310F200546E8E /* Sources */ = { 300 | isa = PBXSourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | FB8EDAF2152310F300546E8E /* Sample_ARCTests.m in Sources */, 304 | FB8EDAFD1523111B00546E8E /* Sample_ProjectTests.m in Sources */, 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | /* End PBXSourcesBuildPhase section */ 309 | 310 | /* Begin PBXTargetDependency section */ 311 | FB8EDAE9152310F300546E8E /* PBXTargetDependency */ = { 312 | isa = PBXTargetDependency; 313 | target = FB8EDAC7152310F200546E8E /* Sample ARC */; 314 | targetProxy = FB8EDAE8152310F300546E8E /* PBXContainerItemProxy */; 315 | }; 316 | /* End PBXTargetDependency section */ 317 | 318 | /* Begin PBXVariantGroup section */ 319 | FB8EDAD5152310F200546E8E /* InfoPlist.strings */ = { 320 | isa = PBXVariantGroup; 321 | children = ( 322 | FB8EDAD6152310F200546E8E /* en */, 323 | ); 324 | name = InfoPlist.strings; 325 | sourceTree = ""; 326 | }; 327 | FB8EDAED152310F300546E8E /* InfoPlist.strings */ = { 328 | isa = PBXVariantGroup; 329 | children = ( 330 | FB8EDAEE152310F300546E8E /* en */, 331 | ); 332 | name = InfoPlist.strings; 333 | sourceTree = ""; 334 | }; 335 | /* End PBXVariantGroup section */ 336 | 337 | /* Begin XCBuildConfiguration section */ 338 | FB8EDAF3152310F300546E8E /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 343 | CLANG_ENABLE_OBJC_ARC = YES; 344 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 345 | COPY_PHASE_STRIP = NO; 346 | GCC_C_LANGUAGE_STANDARD = gnu99; 347 | GCC_DYNAMIC_NO_PIC = NO; 348 | GCC_OPTIMIZATION_LEVEL = 0; 349 | GCC_PREPROCESSOR_DEFINITIONS = ( 350 | "DEBUG=1", 351 | "$(inherited)", 352 | ); 353 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 354 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 355 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 356 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 357 | GCC_WARN_UNUSED_VARIABLE = YES; 358 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 359 | SDKROOT = iphoneos; 360 | TARGETED_DEVICE_FAMILY = "1,2"; 361 | }; 362 | name = Debug; 363 | }; 364 | FB8EDAF4152310F300546E8E /* Release */ = { 365 | isa = XCBuildConfiguration; 366 | buildSettings = { 367 | ALWAYS_SEARCH_USER_PATHS = NO; 368 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 369 | CLANG_ENABLE_OBJC_ARC = YES; 370 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 371 | COPY_PHASE_STRIP = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu99; 373 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 376 | GCC_WARN_UNUSED_VARIABLE = YES; 377 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 378 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 379 | SDKROOT = iphoneos; 380 | TARGETED_DEVICE_FAMILY = "1,2"; 381 | VALIDATE_PRODUCT = YES; 382 | }; 383 | name = Release; 384 | }; 385 | FB8EDAF6152310F300546E8E /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 389 | GCC_PREFIX_HEADER = "Sample ARC/Sample ARC-Prefix.pch"; 390 | INFOPLIST_FILE = "Sample ARC/Sample ARC-Info.plist"; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | WRAPPER_EXTENSION = app; 393 | }; 394 | name = Debug; 395 | }; 396 | FB8EDAF7152310F300546E8E /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 400 | GCC_PREFIX_HEADER = "Sample ARC/Sample ARC-Prefix.pch"; 401 | INFOPLIST_FILE = "Sample ARC/Sample ARC-Info.plist"; 402 | PRODUCT_NAME = "$(TARGET_NAME)"; 403 | WRAPPER_EXTENSION = app; 404 | }; 405 | name = Release; 406 | }; 407 | FB8EDAF9152310F300546E8E /* Debug */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Sample ARC.app/Sample ARC"; 411 | FRAMEWORK_SEARCH_PATHS = ( 412 | "$(SDKROOT)/Developer/Library/Frameworks", 413 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 414 | ); 415 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 416 | GCC_PREFIX_HEADER = "Sample ARC/Sample ARC-Prefix.pch"; 417 | INFOPLIST_FILE = "Sample ARCTests/Sample ARCTests-Info.plist"; 418 | PRODUCT_NAME = "$(TARGET_NAME)"; 419 | TEST_HOST = "$(BUNDLE_LOADER)"; 420 | WRAPPER_EXTENSION = octest; 421 | }; 422 | name = Debug; 423 | }; 424 | FB8EDAFA152310F300546E8E /* Release */ = { 425 | isa = XCBuildConfiguration; 426 | buildSettings = { 427 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Sample ARC.app/Sample ARC"; 428 | FRAMEWORK_SEARCH_PATHS = ( 429 | "$(SDKROOT)/Developer/Library/Frameworks", 430 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 431 | ); 432 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 433 | GCC_PREFIX_HEADER = "Sample ARC/Sample ARC-Prefix.pch"; 434 | INFOPLIST_FILE = "Sample ARCTests/Sample ARCTests-Info.plist"; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | TEST_HOST = "$(BUNDLE_LOADER)"; 437 | WRAPPER_EXTENSION = octest; 438 | }; 439 | name = Release; 440 | }; 441 | /* End XCBuildConfiguration section */ 442 | 443 | /* Begin XCConfigurationList section */ 444 | FB8EDAC2152310F100546E8E /* Build configuration list for PBXProject "Sample ARC" */ = { 445 | isa = XCConfigurationList; 446 | buildConfigurations = ( 447 | FB8EDAF3152310F300546E8E /* Debug */, 448 | FB8EDAF4152310F300546E8E /* Release */, 449 | ); 450 | defaultConfigurationIsVisible = 0; 451 | defaultConfigurationName = Release; 452 | }; 453 | FB8EDAF5152310F300546E8E /* Build configuration list for PBXNativeTarget "Sample ARC" */ = { 454 | isa = XCConfigurationList; 455 | buildConfigurations = ( 456 | FB8EDAF6152310F300546E8E /* Debug */, 457 | FB8EDAF7152310F300546E8E /* Release */, 458 | ); 459 | defaultConfigurationIsVisible = 0; 460 | defaultConfigurationName = Release; 461 | }; 462 | FB8EDAF8152310F300546E8E /* Build configuration list for PBXNativeTarget "Sample ARCTests" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | FB8EDAF9152310F300546E8E /* Debug */, 466 | FB8EDAFA152310F300546E8E /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | defaultConfigurationName = Release; 470 | }; 471 | /* End XCConfigurationList section */ 472 | }; 473 | rootObject = FB8EDABF152310F100546E8E /* Project object */; 474 | } 475 | --------------------------------------------------------------------------------