├── Example ├── Example │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── main.m │ ├── Example-Prefix.pch │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── Example-Info.plist │ ├── ViewController.h │ ├── AppDelegate.h │ ├── TestReceiver.h │ ├── TestReceiver.m │ ├── ViewController.m │ ├── AppDelegate.m │ └── Base.lproj │ │ └── Main.storyboard └── Example.xcodeproj │ └── project.pbxproj ├── LICENSE ├── README.md ├── INTUAutoRemoveObserver.h └── INTUAutoRemoveObserver.m /Example/Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Example/Example/Example-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Intuit Inc 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Example/Example/Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.intuit.${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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Example/Example/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit Inc 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining 9 | // a copy of this software and associated documentation files (the 10 | // "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, 12 | // distribute, sublicense, and/or sell copies of the Software, and to 13 | // permit persons to whom the Software is furnished to do so, subject to 14 | // the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be 17 | // included in all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | #import 28 | 29 | @interface ViewController : UIViewController 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit Inc 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining 9 | // a copy of this software and associated documentation files (the 10 | // "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, 12 | // distribute, sublicense, and/or sell copies of the Software, and to 13 | // permit persons to whom the Software is furnished to do so, subject to 14 | // the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be 17 | // included in all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | #import 28 | 29 | @interface AppDelegate : UIResponder 30 | 31 | @property (strong, nonatomic) UIWindow *window; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Example/Example/TestReceiver.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestReceiver.h 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit Inc 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining 9 | // a copy of this software and associated documentation files (the 10 | // "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, 12 | // distribute, sublicense, and/or sell copies of the Software, and to 13 | // permit persons to whom the Software is furnished to do so, subject to 14 | // the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be 17 | // included in all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | #import 28 | 29 | @interface TestReceiver : NSObject 30 | 31 | @property (nonatomic, strong) NSString* myString; 32 | 33 | -(void)observeMe; 34 | 35 | -(void)addBlockObserver; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/Example/TestReceiver.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestReceiver.m 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit Inc 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining 9 | // a copy of this software and associated documentation files (the 10 | // "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, 12 | // distribute, sublicense, and/or sell copies of the Software, and to 13 | // permit persons to whom the Software is furnished to do so, subject to 14 | // the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be 17 | // included in all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | #import "TestReceiver.h" 28 | #import "INTUAutoRemoveObserver.h" 29 | 30 | @implementation TestReceiver 31 | 32 | -(void)observeMe 33 | { 34 | NSLog(@"Hello from TestReceiver"); 35 | } 36 | 37 | -(void)addBlockObserver 38 | { 39 | NSLog(@"TestReceiver addBlockObserver"); 40 | 41 | NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; 42 | __typeof(self) __weak weakSelf = self; 43 | 44 | [INTUAutoRemoveObserver addObserver:self 45 | forName:@"Broadcast" 46 | object:nil 47 | queue:mainQueue 48 | usingBlock:^(NSNotification * note) { 49 | NSLog(@"Hello from TestReceiver block"); 50 | [weakSelf observeMe]; 51 | }]; 52 | } 53 | 54 | -(void)dealloc 55 | { 56 | NSLog(@"TestReceiver dealloc"); 57 | } 58 | 59 | -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 60 | { 61 | NSLog(@"TestReceiver observing keyPath %@", keyPath); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Example/Example/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit Inc 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining 9 | // a copy of this software and associated documentation files (the 10 | // "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, 12 | // distribute, sublicense, and/or sell copies of the Software, and to 13 | // permit persons to whom the Software is furnished to do so, subject to 14 | // the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be 17 | // included in all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | #import "ViewController.h" 28 | #import "INTUAutoRemoveObserver.h" 29 | #import "TestReceiver.h" 30 | 31 | @interface ViewController () 32 | 33 | @property (nonatomic, strong) TestReceiver* aTestReceiver; 34 | 35 | @property (nonatomic, copy) NSString* testString; 36 | 37 | @end 38 | 39 | @implementation ViewController 40 | 41 | - (void)viewDidLoad 42 | { 43 | [super viewDidLoad]; 44 | 45 | self.aTestReceiver = [TestReceiver new]; 46 | 47 | [INTUAutoRemoveObserver addObserver:self.aTestReceiver selector:@selector(observeMe) name:@"Broadcast" object:nil]; 48 | } 49 | 50 | - (IBAction)postNotification:(id)sender 51 | { 52 | NSLog(@"Sending broadcast"); 53 | [[NSNotificationCenter defaultCenter] postNotificationName:@"Broadcast" object:self]; 54 | 55 | NSLog(@"Changing testString"); 56 | self.testString = @"Foo"; 57 | } 58 | 59 | - (IBAction)deleteReceiver:(id)sender 60 | { 61 | NSLog(@"deleting aTestReceiver"); 62 | self.aTestReceiver = nil; 63 | } 64 | 65 | - (IBAction)addBlockObserver:(id)sender 66 | { 67 | NSLog(@"addBlockObserver"); 68 | if (!self.aTestReceiver) { 69 | NSLog(@"Creating new TestReceiver"); 70 | self.aTestReceiver = [TestReceiver new]; 71 | } 72 | 73 | [self.aTestReceiver addBlockObserver]; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AutoRemoveObserver 2 | ================== 3 | 4 | The problem with NotificationCenter and KVO observers is that you have to remember to remove 5 | the observing object when it gets dealloc'ed or your app will crash on the next notification. 6 | 7 | The methods below create a small "remover" object that is associated with the observer object 8 | such that when the observer object gets dealloc'ed this object will also get dealloc'ed *and* 9 | remove the observations. 10 | 11 | N.B.: This class is designed to remove the observer when the observer is dealloc'ed. If you 12 | need to remove the observer before that then you should use the standard methods and be sure 13 | to handle the dealloc case yourself. 14 | 15 | Instead of writing: 16 | 17 | // Selector based 18 | [[NSNotificationCenter defaultCenter] addObserver:notificationObserver 19 | selector:notificationSelector 20 | name:notificationName 21 | object:notificationSender]; 22 | 23 | // Block based 24 | [[NSNotificationCenter defaultCenter] addObserverForName:name 25 | object:obj 26 | queue:queue 27 | usingBlock:block]; 28 | 29 | // KVO 30 | [self addObserver:anObserver forKeyPath:keyPath options:options context:context]; 31 | 32 | you write: 33 | 34 | // Selector based 35 | [INTUAutoRemoveObserver addObserver:notificationObserver 36 | selector:notificationSelector 37 | name:notificationName 38 | object:notificationSender]; 39 | 40 | // Block based 41 | [INTUAutoRemoveObserver addObserver:self 42 | forName:name 43 | object:obj 44 | queue:queue 45 | usingBlock:block]; 46 | 47 | // KVO 48 | [INTUAutoRemoveObserver addObserver:anObserver 49 | forKeyPath:keyPath 50 | options:options 51 | context:context 52 | onReceiverObject:self]; 53 | 54 | E.g.: 55 | 56 | // Selector based 57 | [INTUAutoRemoveObserver addObserver:self 58 | selector:@selector(myMethod) 59 | name:@"BroadcastNotification" 60 | object:nil]; 61 | 62 | // Block based 63 | MyObject* __weak weakSelf = self; // So the block doesn't retain us 64 | [INTUAutoRemoveObserver addObserver:self 65 | forName:@"BroadcastNotification" 66 | object:nil 67 | queue:[NSOperationQueue mainQueue] 68 | usingBlock:^(NSNotification *note) { 69 | [weakSelf observeMe]; 70 | }]; 71 | 72 | // KVO 73 | [INTUAutoRemoveObserver addObserver:self // self or some observer object. When this is dealloc'ed then observer is removed. 74 | forKeyPath:NSStringFromSelector(@selector(myProperty)) 75 | options:NSKeyValueObservingOptionNew 76 | context:nil 77 | onReceiverObject:self]; 78 | 79 | N.B.: If the observer is self you will see an error in the log file about the instance being deallocated while key 80 | observers were still registered to it (even though they are removed as a side effect of self getting dealloc'ed) 81 | when self is dealloc'ed. 82 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Example 4 | // 5 | // Created by Jeff Shulman on 3/26/14. 6 | // Copyright (c) 2014 Intuit Inc 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining 9 | // a copy of this software and associated documentation files (the 10 | // "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, 12 | // distribute, sublicense, and/or sell copies of the Software, and to 13 | // permit persons to whom the Software is furnished to do so, subject to 14 | // the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be 17 | // included in all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | #import "AppDelegate.h" 28 | 29 | @implementation AppDelegate 30 | 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 32 | { 33 | // Override point for customization after application launch. 34 | return YES; 35 | } 36 | 37 | - (void)applicationWillResignActive:(UIApplication *)application 38 | { 39 | // 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. 40 | // 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. 41 | } 42 | 43 | - (void)applicationDidEnterBackground:(UIApplication *)application 44 | { 45 | // 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. 46 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 47 | } 48 | 49 | - (void)applicationWillEnterForeground:(UIApplication *)application 50 | { 51 | // 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. 52 | } 53 | 54 | - (void)applicationDidBecomeActive:(UIApplication *)application 55 | { 56 | // 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. 57 | } 58 | 59 | - (void)applicationWillTerminate:(UIApplication *)application 60 | { 61 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /INTUAutoRemoveObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // INTUAutoRemoveObserver.h 3 | // 4 | // Created by Jeff Shulman on 3/18/14. 5 | // Copyright (c) 2014 Intuit Inc 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining 8 | // a copy of this software and associated documentation files (the 9 | // "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, 11 | // distribute, sublicense, and/or sell copies of the Software, and to 12 | // permit persons to whom the Software is furnished to do so, subject to 13 | // the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | // 26 | // The problem with NotificationCenter observers is that you have to remember to remove 27 | // the observing object when it gets dealloc'ed or your app will crash on the next notification. 28 | // 29 | // The methods below create a small "remover" object that is associated with the observer object 30 | // such that when the observer object gets dealloc'ed this object will also get dealloc'ed *and* 31 | // remove the observations. 32 | // 33 | // N.B.: This class is designed to remove the observer when the observer is dealloc'ed. If you 34 | // need to remove the observer before that then you should use the standard methods and be sure 35 | // to handle the dealloc case yourself. 36 | // 37 | // Instead of writing: 38 | // 39 | // // Selector based 40 | // [[NSNotificationCenter defaultCenter] addObserver:notificationObserver 41 | // selector:notificationSelector 42 | // name:notificationName 43 | // object:notificationSender]; 44 | // 45 | // // Block based 46 | // [[NSNotificationCenter defaultCenter] addObserverForName:name 47 | // object:obj 48 | // queue:queue 49 | // usingBlock:block]; 50 | // 51 | // you write: 52 | // 53 | // // Selector based 54 | // [INTUAutoRemoveObserver addObserver:notificationObserver 55 | // selector:notificationSelector 56 | // name:notificationName 57 | // object:notificationSender]; 58 | // 59 | // // Block based 60 | // [INTUAutoRemoveObserver addObserver:self 61 | // forName:name 62 | // object:obj 63 | // queue:queue 64 | // usingBlock:block]; 65 | // 66 | // E.g.: 67 | // 68 | // // Selector based 69 | // [INTUAutoRemoveObserver addObserver:self 70 | // selector:@selector(myMethod) 71 | // name:@"BroadcastNotification" 72 | // object:nil]; 73 | // 74 | // // Block based 75 | // MyObject* __weak weakSelf = self; // So the block doesn't retain us 76 | // [INTUAutoRemoveObserver addObserver:self 77 | // forName:@"BroadcastNotification" 78 | // object:nil 79 | // queue:[NSOperationQueue mainQueue] 80 | // usingBlock:^(NSNotification *note) { 81 | // [weakSelf observeMe]; 82 | // }]; 83 | 84 | #import 85 | 86 | @interface INTUAutoRemoveObserver : NSObject 87 | 88 | // Notification Center observers 89 | +(void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender; 90 | 91 | +(void)addObserver:(id)notificationObserver forName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification * note))block; 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /INTUAutoRemoveObserver.m: -------------------------------------------------------------------------------- 1 | // 2 | // INTUAutoRemoveObserver.m 3 | // 4 | // Created by Jeff Shulman on 3/18/14. 5 | // Copyright (c) 2014 Intuit Inc 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining 8 | // a copy of this software and associated documentation files (the 9 | // "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, 11 | // distribute, sublicense, and/or sell copies of the Software, and to 12 | // permit persons to whom the Software is furnished to do so, subject to 13 | // the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | #import "INTUAutoRemoveObserver.h" 27 | #import 28 | 29 | @interface INTUAutoRemoveObserver () 30 | 31 | // The observer is "unsafe_unretained" since we don't want a strong reference to change the 32 | // observer refcount and we don't want to be weak since our dealloc will be called after 33 | // the observer has been dealloc'ed itself. 34 | @property (nonatomic, unsafe_unretained) id notificationObserver; 35 | 36 | @property (nonatomic, assign) id notificationSender; 37 | @property (nonatomic, copy) NSString* notificationName; 38 | 39 | // This is to store a reference to any block created observer 40 | @property (nonatomic, strong) id blockObserver; 41 | 42 | @end 43 | 44 | @implementation INTUAutoRemoveObserver 45 | 46 | +(void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender 47 | { 48 | // Create the remover object 49 | INTUAutoRemoveObserver* remover = [[INTUAutoRemoveObserver alloc] init]; 50 | remover.notificationObserver = notificationObserver; 51 | remover.notificationName = notificationName; 52 | remover.notificationSender = notificationSender; 53 | 54 | // Keep this object around for the lifetime of the observer 55 | objc_setAssociatedObject(notificationObserver, (__bridge const void *)(remover), remover, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 56 | 57 | // Now register for the notification 58 | [[NSNotificationCenter defaultCenter] addObserver:notificationObserver 59 | selector:notificationSelector 60 | name:notificationName 61 | object:notificationSender]; 62 | } 63 | 64 | +(void)addObserver:(id)notificationObserver forName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *))block; 65 | { 66 | // Create the remover object 67 | INTUAutoRemoveObserver* remover = [[INTUAutoRemoveObserver alloc] init]; 68 | 69 | id blockObserver = [[NSNotificationCenter defaultCenter] addObserverForName:name 70 | object:obj 71 | queue:queue 72 | usingBlock:block]; 73 | 74 | // Keep this object around for the lifetime of the notificationObserver object 75 | objc_setAssociatedObject(notificationObserver, (__bridge const void *)(remover), remover, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 76 | 77 | remover.blockObserver = blockObserver; 78 | } 79 | 80 | -(void)dealloc 81 | { 82 | if ( self.blockObserver ) { 83 | // A block based notification center observer 84 | [[NSNotificationCenter defaultCenter] removeObserver:self.blockObserver]; 85 | } 86 | else { 87 | // A selector based notification center observer 88 | [[NSNotificationCenter defaultCenter] removeObserver:self.notificationObserver 89 | name:self.notificationName 90 | object:self.notificationSender]; 91 | } 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /Example/Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 29 | 39 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7F32FA4218E3A15500BF3FF4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F32FA4118E3A15500BF3FF4 /* Foundation.framework */; }; 11 | 7F32FA4418E3A15500BF3FF4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F32FA4318E3A15500BF3FF4 /* CoreGraphics.framework */; }; 12 | 7F32FA4618E3A15500BF3FF4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F32FA4518E3A15500BF3FF4 /* UIKit.framework */; }; 13 | 7F32FA4C18E3A15500BF3FF4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F32FA4A18E3A15500BF3FF4 /* InfoPlist.strings */; }; 14 | 7F32FA4E18E3A15500BF3FF4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F32FA4D18E3A15500BF3FF4 /* main.m */; }; 15 | 7F32FA5218E3A15500BF3FF4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F32FA5118E3A15500BF3FF4 /* AppDelegate.m */; }; 16 | 7F32FA5518E3A15500BF3FF4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F32FA5318E3A15500BF3FF4 /* Main.storyboard */; }; 17 | 7F32FA5818E3A15500BF3FF4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F32FA5718E3A15500BF3FF4 /* ViewController.m */; }; 18 | 7F32FA5A18E3A15500BF3FF4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7F32FA5918E3A15500BF3FF4 /* Images.xcassets */; }; 19 | 7F32FA7818E3A16D00BF3FF4 /* INTUAutoRemoveObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F32FA7718E3A16D00BF3FF4 /* INTUAutoRemoveObserver.m */; }; 20 | 7F32FA7B18E3A27B00BF3FF4 /* TestReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F32FA7A18E3A27B00BF3FF4 /* TestReceiver.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 7F32FA3E18E3A15500BF3FF4 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 7F32FA4118E3A15500BF3FF4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 26 | 7F32FA4318E3A15500BF3FF4 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 27 | 7F32FA4518E3A15500BF3FF4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28 | 7F32FA4918E3A15500BF3FF4 /* Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Example-Info.plist"; sourceTree = ""; }; 29 | 7F32FA4B18E3A15500BF3FF4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30 | 7F32FA4D18E3A15500BF3FF4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | 7F32FA4F18E3A15500BF3FF4 /* Example-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Prefix.pch"; sourceTree = ""; }; 32 | 7F32FA5018E3A15500BF3FF4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | 7F32FA5118E3A15500BF3FF4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | 7F32FA5418E3A15500BF3FF4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 35 | 7F32FA5618E3A15500BF3FF4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 36 | 7F32FA5718E3A15500BF3FF4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 37 | 7F32FA5918E3A15500BF3FF4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 38 | 7F32FA6018E3A15500BF3FF4 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 39 | 7F32FA7618E3A16D00BF3FF4 /* INTUAutoRemoveObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INTUAutoRemoveObserver.h; path = ../INTUAutoRemoveObserver.h; sourceTree = ""; }; 40 | 7F32FA7718E3A16D00BF3FF4 /* INTUAutoRemoveObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INTUAutoRemoveObserver.m; path = ../INTUAutoRemoveObserver.m; sourceTree = ""; }; 41 | 7F32FA7918E3A27B00BF3FF4 /* TestReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestReceiver.h; sourceTree = ""; }; 42 | 7F32FA7A18E3A27B00BF3FF4 /* TestReceiver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestReceiver.m; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | 7F32FA3B18E3A15500BF3FF4 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | 7F32FA4418E3A15500BF3FF4 /* CoreGraphics.framework in Frameworks */, 51 | 7F32FA4618E3A15500BF3FF4 /* UIKit.framework in Frameworks */, 52 | 7F32FA4218E3A15500BF3FF4 /* Foundation.framework in Frameworks */, 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | 7F32FA3518E3A15500BF3FF4 = { 60 | isa = PBXGroup; 61 | children = ( 62 | 7F32FA7618E3A16D00BF3FF4 /* INTUAutoRemoveObserver.h */, 63 | 7F32FA7718E3A16D00BF3FF4 /* INTUAutoRemoveObserver.m */, 64 | 7F32FA4718E3A15500BF3FF4 /* Example */, 65 | 7F32FA4018E3A15500BF3FF4 /* Frameworks */, 66 | 7F32FA3F18E3A15500BF3FF4 /* Products */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | 7F32FA3F18E3A15500BF3FF4 /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 7F32FA3E18E3A15500BF3FF4 /* Example.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | 7F32FA4018E3A15500BF3FF4 /* Frameworks */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 7F32FA4118E3A15500BF3FF4 /* Foundation.framework */, 82 | 7F32FA4318E3A15500BF3FF4 /* CoreGraphics.framework */, 83 | 7F32FA4518E3A15500BF3FF4 /* UIKit.framework */, 84 | 7F32FA6018E3A15500BF3FF4 /* XCTest.framework */, 85 | ); 86 | name = Frameworks; 87 | sourceTree = ""; 88 | }; 89 | 7F32FA4718E3A15500BF3FF4 /* Example */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 7F32FA5018E3A15500BF3FF4 /* AppDelegate.h */, 93 | 7F32FA5118E3A15500BF3FF4 /* AppDelegate.m */, 94 | 7F32FA5318E3A15500BF3FF4 /* Main.storyboard */, 95 | 7F32FA5618E3A15500BF3FF4 /* ViewController.h */, 96 | 7F32FA5718E3A15500BF3FF4 /* ViewController.m */, 97 | 7F32FA7918E3A27B00BF3FF4 /* TestReceiver.h */, 98 | 7F32FA7A18E3A27B00BF3FF4 /* TestReceiver.m */, 99 | 7F32FA5918E3A15500BF3FF4 /* Images.xcassets */, 100 | 7F32FA4818E3A15500BF3FF4 /* Supporting Files */, 101 | ); 102 | path = Example; 103 | sourceTree = ""; 104 | }; 105 | 7F32FA4818E3A15500BF3FF4 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 7F32FA4918E3A15500BF3FF4 /* Example-Info.plist */, 109 | 7F32FA4A18E3A15500BF3FF4 /* InfoPlist.strings */, 110 | 7F32FA4D18E3A15500BF3FF4 /* main.m */, 111 | 7F32FA4F18E3A15500BF3FF4 /* Example-Prefix.pch */, 112 | ); 113 | name = "Supporting Files"; 114 | sourceTree = ""; 115 | }; 116 | /* End PBXGroup section */ 117 | 118 | /* Begin PBXNativeTarget section */ 119 | 7F32FA3D18E3A15500BF3FF4 /* Example */ = { 120 | isa = PBXNativeTarget; 121 | buildConfigurationList = 7F32FA7018E3A15500BF3FF4 /* Build configuration list for PBXNativeTarget "Example" */; 122 | buildPhases = ( 123 | 7F32FA3A18E3A15500BF3FF4 /* Sources */, 124 | 7F32FA3B18E3A15500BF3FF4 /* Frameworks */, 125 | 7F32FA3C18E3A15500BF3FF4 /* Resources */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | ); 131 | name = Example; 132 | productName = Example; 133 | productReference = 7F32FA3E18E3A15500BF3FF4 /* Example.app */; 134 | productType = "com.apple.product-type.application"; 135 | }; 136 | /* End PBXNativeTarget section */ 137 | 138 | /* Begin PBXProject section */ 139 | 7F32FA3618E3A15500BF3FF4 /* Project object */ = { 140 | isa = PBXProject; 141 | attributes = { 142 | LastUpgradeCheck = 0510; 143 | ORGANIZATIONNAME = Intuit; 144 | }; 145 | buildConfigurationList = 7F32FA3918E3A15500BF3FF4 /* Build configuration list for PBXProject "Example" */; 146 | compatibilityVersion = "Xcode 3.2"; 147 | developmentRegion = English; 148 | hasScannedForEncodings = 0; 149 | knownRegions = ( 150 | en, 151 | Base, 152 | ); 153 | mainGroup = 7F32FA3518E3A15500BF3FF4; 154 | productRefGroup = 7F32FA3F18E3A15500BF3FF4 /* Products */; 155 | projectDirPath = ""; 156 | projectRoot = ""; 157 | targets = ( 158 | 7F32FA3D18E3A15500BF3FF4 /* Example */, 159 | ); 160 | }; 161 | /* End PBXProject section */ 162 | 163 | /* Begin PBXResourcesBuildPhase section */ 164 | 7F32FA3C18E3A15500BF3FF4 /* Resources */ = { 165 | isa = PBXResourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | 7F32FA5A18E3A15500BF3FF4 /* Images.xcassets in Resources */, 169 | 7F32FA4C18E3A15500BF3FF4 /* InfoPlist.strings in Resources */, 170 | 7F32FA5518E3A15500BF3FF4 /* Main.storyboard in Resources */, 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | /* End PBXResourcesBuildPhase section */ 175 | 176 | /* Begin PBXSourcesBuildPhase section */ 177 | 7F32FA3A18E3A15500BF3FF4 /* Sources */ = { 178 | isa = PBXSourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 7F32FA7818E3A16D00BF3FF4 /* INTUAutoRemoveObserver.m in Sources */, 182 | 7F32FA7B18E3A27B00BF3FF4 /* TestReceiver.m in Sources */, 183 | 7F32FA5818E3A15500BF3FF4 /* ViewController.m in Sources */, 184 | 7F32FA5218E3A15500BF3FF4 /* AppDelegate.m in Sources */, 185 | 7F32FA4E18E3A15500BF3FF4 /* main.m in Sources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXSourcesBuildPhase section */ 190 | 191 | /* Begin PBXVariantGroup section */ 192 | 7F32FA4A18E3A15500BF3FF4 /* InfoPlist.strings */ = { 193 | isa = PBXVariantGroup; 194 | children = ( 195 | 7F32FA4B18E3A15500BF3FF4 /* en */, 196 | ); 197 | name = InfoPlist.strings; 198 | sourceTree = ""; 199 | }; 200 | 7F32FA5318E3A15500BF3FF4 /* Main.storyboard */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 7F32FA5418E3A15500BF3FF4 /* Base */, 204 | ); 205 | name = Main.storyboard; 206 | sourceTree = ""; 207 | }; 208 | /* End PBXVariantGroup section */ 209 | 210 | /* Begin XCBuildConfiguration section */ 211 | 7F32FA6E18E3A15500BF3FF4 /* Debug */ = { 212 | isa = XCBuildConfiguration; 213 | buildSettings = { 214 | ALWAYS_SEARCH_USER_PATHS = NO; 215 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 216 | CLANG_CXX_LIBRARY = "libc++"; 217 | CLANG_ENABLE_MODULES = YES; 218 | CLANG_ENABLE_OBJC_ARC = YES; 219 | CLANG_WARN_BOOL_CONVERSION = YES; 220 | CLANG_WARN_CONSTANT_CONVERSION = YES; 221 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 222 | CLANG_WARN_EMPTY_BODY = YES; 223 | CLANG_WARN_ENUM_CONVERSION = YES; 224 | CLANG_WARN_INT_CONVERSION = YES; 225 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 226 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 227 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 228 | COPY_PHASE_STRIP = NO; 229 | GCC_C_LANGUAGE_STANDARD = gnu99; 230 | GCC_DYNAMIC_NO_PIC = NO; 231 | GCC_OPTIMIZATION_LEVEL = 0; 232 | GCC_PREPROCESSOR_DEFINITIONS = ( 233 | "DEBUG=1", 234 | "$(inherited)", 235 | ); 236 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 238 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 239 | GCC_WARN_UNDECLARED_SELECTOR = YES; 240 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 241 | GCC_WARN_UNUSED_FUNCTION = YES; 242 | GCC_WARN_UNUSED_VARIABLE = YES; 243 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 244 | ONLY_ACTIVE_ARCH = YES; 245 | SDKROOT = iphoneos; 246 | }; 247 | name = Debug; 248 | }; 249 | 7F32FA6F18E3A15500BF3FF4 /* Release */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | ALWAYS_SEARCH_USER_PATHS = NO; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_MODULES = YES; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 260 | CLANG_WARN_EMPTY_BODY = YES; 261 | CLANG_WARN_ENUM_CONVERSION = YES; 262 | CLANG_WARN_INT_CONVERSION = YES; 263 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 265 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 266 | COPY_PHASE_STRIP = YES; 267 | ENABLE_NS_ASSERTIONS = NO; 268 | GCC_C_LANGUAGE_STANDARD = gnu99; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 276 | SDKROOT = iphoneos; 277 | VALIDATE_PRODUCT = YES; 278 | }; 279 | name = Release; 280 | }; 281 | 7F32FA7118E3A15500BF3FF4 /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 286 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 287 | GCC_PREFIX_HEADER = "Example/Example-Prefix.pch"; 288 | INFOPLIST_FILE = "Example/Example-Info.plist"; 289 | PRODUCT_NAME = "$(TARGET_NAME)"; 290 | WRAPPER_EXTENSION = app; 291 | }; 292 | name = Debug; 293 | }; 294 | 7F32FA7218E3A15500BF3FF4 /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 298 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 299 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 300 | GCC_PREFIX_HEADER = "Example/Example-Prefix.pch"; 301 | INFOPLIST_FILE = "Example/Example-Info.plist"; 302 | PRODUCT_NAME = "$(TARGET_NAME)"; 303 | WRAPPER_EXTENSION = app; 304 | }; 305 | name = Release; 306 | }; 307 | /* End XCBuildConfiguration section */ 308 | 309 | /* Begin XCConfigurationList section */ 310 | 7F32FA3918E3A15500BF3FF4 /* Build configuration list for PBXProject "Example" */ = { 311 | isa = XCConfigurationList; 312 | buildConfigurations = ( 313 | 7F32FA6E18E3A15500BF3FF4 /* Debug */, 314 | 7F32FA6F18E3A15500BF3FF4 /* Release */, 315 | ); 316 | defaultConfigurationIsVisible = 0; 317 | defaultConfigurationName = Release; 318 | }; 319 | 7F32FA7018E3A15500BF3FF4 /* Build configuration list for PBXNativeTarget "Example" */ = { 320 | isa = XCConfigurationList; 321 | buildConfigurations = ( 322 | 7F32FA7118E3A15500BF3FF4 /* Debug */, 323 | 7F32FA7218E3A15500BF3FF4 /* Release */, 324 | ); 325 | defaultConfigurationIsVisible = 0; 326 | defaultConfigurationName = Release; 327 | }; 328 | /* End XCConfigurationList section */ 329 | }; 330 | rootObject = 7F32FA3618E3A15500BF3FF4 /* Project object */; 331 | } 332 | --------------------------------------------------------------------------------