From 6c2f14bc180418cfad42582be6ef1cc6a5413368 Mon Sep 17 00:00:00 2001 From: "gtm.daemon" Date: Fri, 4 Jun 2010 15:35:57 +0000 Subject: [Author: dmaclach] Turns on the undeclared-selector warning. This may cause builds to fail if they are using our configs. Also cleaned up some whitespace issues. R=thomasvl DELTA=94 (71 added, 22 deleted, 1 changed) --- Foundation/GTMNSObject+KeyValueObserving.m | 315 ++++++++++++++++------------- 1 file changed, 173 insertions(+), 142 deletions(-) (limited to 'Foundation/GTMNSObject+KeyValueObserving.m') diff --git a/Foundation/GTMNSObject+KeyValueObserving.m b/Foundation/GTMNSObject+KeyValueObserving.m index 9b9acce..3fdc24e 100644 --- a/Foundation/GTMNSObject+KeyValueObserving.m +++ b/Foundation/GTMNSObject+KeyValueObserving.m @@ -6,9 +6,9 @@ // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -23,7 +23,7 @@ // Created by Michael Ash on 10/15/08. // -// This code is based on code by Michael Ash. +// This code is based on code by Michael Ash. // See comment in header. #import "GTMDefines.h" #import "GTMNSObject+KeyValueObserving.h" @@ -32,9 +32,9 @@ #import "GTMObjC2Runtime.h" #import "GTMMethodCheck.h" -// A singleton that works as a dispatch center for KVO +// A singleton that works as a dispatch center for KVO // -[NSObject observeValueForKeyPath:ofObject:change:context:] and turns them -// into selector dispatches. It stores a collection of +// into selector dispatches. It stores a collection of // GTMKeyValueObservingHelpers, and keys them via the key generated by // -dictionaryKeyForObserver:ofObject:forKeyPath:selector. @interface GTMKeyValueObservingCenter : NSObject { @@ -44,19 +44,19 @@ + (id)defaultCenter; -- (void)addObserver:(id)observer - ofObject:(id)target - forKeyPath:(NSString *)keyPath - selector:(SEL)selector - userInfo:(id)userInfo +- (void)addObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo options:(NSKeyValueObservingOptions)options; -- (void)removeObserver:(id)observer - ofObject:(id)target - forKeyPath:(NSString *)keyPath +- (void)removeObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath selector:(SEL)selector; -- (id)dictionaryKeyForObserver:(id)observer - ofObject:(id)target - forKeyPath:(NSString *)keyPath +- (id)dictionaryKeyForObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath selector:(SEL)selector; @end @@ -69,43 +69,43 @@ NSString* keyPath_; } -- (id)initWithObserver:(id)observer - object:(id)target - keyPath:(NSString *)keyPath - selector:(SEL)selector - userInfo:(id)userInfo +- (id)initWithObserver:(id)observer + object:(id)target + keyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo options:(NSKeyValueObservingOptions)options; - (void)deregister; @end @interface GTMKeyValueChangeNotification () -- (id)initWithKeyPath:(NSString *)keyPath ofObject:(id)object +- (id)initWithKeyPath:(NSString *)keyPath ofObject:(id)object userInfo:(id)userInfo change:(NSDictionary *)change; @end @implementation GTMKeyValueObservingHelper -// For info how and why we use these statics: +// For info how and why we use these statics: // http://lists.apple.com/archives/cocoa-dev/2006/Jul/msg01038.html static char GTMKeyValueObservingHelperContextData; -static char* GTMKeyValueObservingHelperContext +static char* GTMKeyValueObservingHelperContext = >MKeyValueObservingHelperContextData; -- (id)initWithObserver:(id)observer - object:(id)target - keyPath:(NSString *)keyPath - selector:(SEL)selector +- (id)initWithObserver:(id)observer + object:(id)target + keyPath:(NSString *)keyPath + selector:(SEL)selector userInfo:(id)userInfo options:(NSKeyValueObservingOptions)options { if((self = [super init])) { observer_ = observer; selector_ = selector; userInfo_ = [userInfo retain]; - + target_ = target; keyPath_ = [keyPath retain]; - + [target addObserver:self forKeyPath:keyPath options:options @@ -116,8 +116,8 @@ static char* GTMKeyValueObservingHelperContext - (NSString *)description { return [NSString stringWithFormat: - @"%@ ", - [self class], observer_, keyPath_, target_, + @"%@ ", + [self class], observer_, keyPath_, target_, NSStringFromSelector(selector_)]; } @@ -143,15 +143,15 @@ static char* GTMKeyValueObservingHelperContext [super dealloc]; } -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change context:(void *)context { if(context == GTMKeyValueObservingHelperContext) { - GTMKeyValueChangeNotification *notification + GTMKeyValueChangeNotification *notification = [[GTMKeyValueChangeNotification alloc] initWithKeyPath:keyPath - ofObject:object - userInfo:userInfo_ + ofObject:object + userInfo:userInfo_ change:change]; [observer_ performSelector:selector_ withObject:notification]; [notification release]; @@ -159,9 +159,9 @@ static char* GTMKeyValueObservingHelperContext // COV_NF_START // There's no way this should ever be called. // If it is, the call will go up to NSObject which will assert. - [super observeValueForKeyPath:keyPath - ofObject:object - change:change + [super observeValueForKeyPath:keyPath + ofObject:object + change:change context:context]; // COV_NF_END } @@ -184,8 +184,8 @@ static char* GTMKeyValueObservingHelperContext // and the other will set things up so that the failing thread // gets the shared center GTMKeyValueObservingCenter *newCenter = [[self alloc] init]; - if(!objc_atomicCompareAndSwapGlobalBarrier(nil, - newCenter, + if(!objc_atomicCompareAndSwapGlobalBarrier(nil, + newCenter, (void *)¢er)) { [newCenter release]; // COV_NF_LINE no guarantee we'll hit this line } @@ -208,41 +208,41 @@ static char* GTMKeyValueObservingHelperContext } // COV_NF_END -- (id)dictionaryKeyForObserver:(id)observer - ofObject:(id)target - forKeyPath:(NSString *)keyPath +- (id)dictionaryKeyForObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath selector:(SEL)selector { NSString *key = nil; if (!target && !keyPath && !selector) { key = [NSString stringWithFormat:@"%p:", observer]; } else { - key = [NSString stringWithFormat:@"%p:%@:%p:%p", + key = [NSString stringWithFormat:@"%p:%@:%p:%p", observer, keyPath, selector, target]; } return key; } -- (void)addObserver:(id)observer - ofObject:(id)target - forKeyPath:(NSString *)keyPath +- (void)addObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath selector:(SEL)selector - userInfo:(id)userInfo + userInfo:(id)userInfo options:(NSKeyValueObservingOptions)options { - GTMKeyValueObservingHelper *helper - = [[GTMKeyValueObservingHelper alloc] initWithObserver:observer - object:target - keyPath:keyPath - selector:selector - userInfo:userInfo + GTMKeyValueObservingHelper *helper + = [[GTMKeyValueObservingHelper alloc] initWithObserver:observer + object:target + keyPath:keyPath + selector:selector + userInfo:userInfo options:options]; - id key = [self dictionaryKeyForObserver:observer - ofObject:target - forKeyPath:keyPath + id key = [self dictionaryKeyForObserver:observer + ofObject:target + forKeyPath:keyPath selector:selector]; @synchronized(self) { GTMKeyValueObservingHelper *oldHelper = [observerHelpers_ objectForKey:key]; if (oldHelper) { - _GTMDevLog(@"%@ already observing %@ forKeyPath %@", + _GTMDevLog(@"%@ already observing %@ forKeyPath %@", observer, target, keyPath); [oldHelper deregister]; } @@ -251,18 +251,18 @@ static char* GTMKeyValueObservingHelperContext [helper release]; } -- (void)removeObserver:(id)observer - ofObject:(id)target - forKeyPath:(NSString *)keyPath +- (void)removeObserver:(id)observer + ofObject:(id)target + forKeyPath:(NSString *)keyPath selector:(SEL)selector { - id key = [self dictionaryKeyForObserver:observer + id key = [self dictionaryKeyForObserver:observer ofObject:target - forKeyPath:keyPath + forKeyPath:keyPath selector:selector]; NSMutableArray *allValidHelperKeys = [NSMutableArray array]; NSArray *allValidHelpers = nil; @synchronized(self) { - + NSString *helperKey; GTM_FOREACH_OBJECT(helperKey, [observerHelpers_ allKeys]) { if ([helperKey hasPrefix:key]) { @@ -271,11 +271,11 @@ static char* GTMKeyValueObservingHelperContext } #if DEBUG if ([allValidHelperKeys count] == 0) { - _GTMDevLog(@"%@ was not observing %@ with keypath %@", + _GTMDevLog(@"%@ was not observing %@ with keypath %@", observer, target, keyPath); } #endif // DEBUG - allValidHelpers = [observerHelpers_ objectsForKeys:allValidHelperKeys + allValidHelpers = [observerHelpers_ objectsForKeys:allValidHelperKeys notFoundMarker:[NSNull null]]; [observerHelpers_ removeObjectsForKeys:allValidHelperKeys]; } @@ -286,61 +286,61 @@ static char* GTMKeyValueObservingHelperContext @implementation NSObject (GTMKeyValueObservingAdditions) -- (void)gtm_addObserver:(id)observer - forKeyPath:(NSString *)keyPath - selector:(SEL)selector - userInfo:(id)userInfo +- (void)gtm_addObserver:(id)observer + forKeyPath:(NSString *)keyPath + selector:(SEL)selector + userInfo:(id)userInfo options:(NSKeyValueObservingOptions)options { - _GTMDevAssert(observer && [keyPath length] && selector, + _GTMDevAssert(observer && [keyPath length] && selector, @"Missing observer, keyPath, or selector"); - GTMKeyValueObservingCenter *center + GTMKeyValueObservingCenter *center = [GTMKeyValueObservingCenter defaultCenter]; GTMAssertSelectorNilOrImplementedWithArguments( observer, - selector, - @encode(GTMKeyValueChangeNotification *), + selector, + @encode(GTMKeyValueChangeNotification *), NULL); - [center addObserver:observer - ofObject:self - forKeyPath:keyPath - selector:selector - userInfo:userInfo + [center addObserver:observer + ofObject:self + forKeyPath:keyPath + selector:selector + userInfo:userInfo options:options]; } -- (void)gtm_removeObserver:(id)observer - forKeyPath:(NSString *)keyPath +- (void)gtm_removeObserver:(id)observer + forKeyPath:(NSString *)keyPath selector:(SEL)selector { - _GTMDevAssert(observer && [keyPath length] && selector, + _GTMDevAssert(observer && [keyPath length] && selector, @"Missing observer, keyPath, or selector"); - GTMKeyValueObservingCenter *center + GTMKeyValueObservingCenter *center = [GTMKeyValueObservingCenter defaultCenter]; GTMAssertSelectorNilOrImplementedWithArguments( observer, - selector, - @encode(GTMKeyValueChangeNotification *), - NULL); - [center removeObserver:observer - ofObject:self - forKeyPath:keyPath + selector, + @encode(GTMKeyValueChangeNotification *), + NULL); + [center removeObserver:observer + ofObject:self + forKeyPath:keyPath selector:selector]; } - (void)gtm_stopObservingAllKeyPaths { - GTMKeyValueObservingCenter *center + GTMKeyValueObservingCenter *center = [GTMKeyValueObservingCenter defaultCenter]; - [center removeObserver:self - ofObject:nil - forKeyPath:nil + [center removeObserver:self + ofObject:nil + forKeyPath:nil selector:Nil]; -} +} @end @implementation GTMKeyValueChangeNotification -- (id)initWithKeyPath:(NSString *)keyPath ofObject:(id)object +- (id)initWithKeyPath:(NSString *)keyPath ofObject:(id)object userInfo:(id)userInfo change:(NSDictionary *)change { if ((self = [super init])) { keyPath_ = [keyPath copy]; @@ -360,9 +360,9 @@ static char* GTMKeyValueObservingHelperContext } - (id)copyWithZone:(NSZone *)zone { - return [[[self class] allocWithZone:zone] initWithKeyPath:keyPath_ + return [[[self class] allocWithZone:zone] initWithKeyPath:keyPath_ ofObject:object_ - userInfo:userInfo_ + userInfo:userInfo_ change:change_]; } @@ -375,7 +375,7 @@ static char* GTMKeyValueObservingHelperContext - (NSString *)description { return [NSString stringWithFormat: - @"%@ ", + @"%@ ", [self class], object_, keyPath_, userInfo_, change_]; } @@ -432,8 +432,8 @@ static void SwizzleClassMethodsInClass(Class cls, SEL sel1, SEL sel2) { // // Debugs // Debugs are mainly for logging all the KVO/KVC that is occurring in your -// application. To enable our KVO debugging, set the GTMDebugKVO environment -// variable to 1 and you will get a whole pile of KVO logging that may help you +// application. To enable our KVO debugging, set the GTMDebugKVO environment +// variable to 1 and you will get a whole pile of KVO logging that may help you // track down problems. // bash - export GTMDebugKVO=1 // csh/tcsh - setenv GTMDebugKVO 1 @@ -452,20 +452,51 @@ static void SwizzleClassMethodsInClass(Class cls, SEL sel1, SEL sel2) { // may never see the bug until it's too late. We try to force KVO issues to // rear their head at the time of the observing if at all possible. // Checks are on by default in debug builds. They can be turned off by defining -// the compile flag GTM_PERFORM_KVO_CHECKS to 0 -// i.e. #define GTM_PERFORM_KVO_CHECKS 0, or set it +// the compile flag GTM_PERFORM_KVO_CHECKS to 0 +// i.e. #define GTM_PERFORM_KVO_CHECKS 0, or set it // in GCC_PREPROCESSOR_DEFINITIONS. // // Checks work at a couple of different levels. -// The most restrictive of the checks is that we set +// The most restrictive of the checks is that we set // |accessInstanceVariablesDirectly| to NO by default. This means that if you // attempt to perform KVO on an instance variable, you will get an exception // thrown. -// Also, when adding an observer, we check to see if any member of the path -// starts or ends with _ which by convention denotes an instance variable. If so +// Also, when adding an observer, we check to see if any member of the path +// starts or ends with _ which by convention denotes an instance variable. If so // we warn you about attempting to access a ivar directly. @interface NSObject (GTMDebugKeyValueObserving) +- (void)_gtmDebugAddObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + context:(void *)context; +- (void)_gtmDebugArrayAddObserver:(NSObject *)observer + toObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + context:(void *)context; +- (void)_gtmDebugRemoveObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath; +- (void)_gtmDebugArrayRemoveObserver:(NSObject *)observer + fromObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath; +- (void)_gtmDebugWillChangeValueForKey:(NSString*)key; +- (void)_gtmDebugDidChangeValueForKey:(NSString*)key; + +#if GTM_PERFORM_KVO_CHECKS + +- (void)_gtmCheckAddObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + context:(void *)context; +- (void)_gtmCheckAddObserver:(NSObject *)observer + toObjectsAtIndexes:(NSIndexSet *)indexes + forKeyPath:(NSString *)keyPath + options:(NSKeyValueObservingOptions)options + context:(void *)context; ++ (BOOL)_gtmAccessInstanceVariablesDirectly; + +#endif // GTM_PERFORM_KVO_CHECKS @end @implementation NSObject (GTMDebugKeyValueObserving) @@ -473,18 +504,18 @@ GTM_METHOD_CHECK(NSObject, _gtmDebugAddObserver:forKeyPath:options:context:); GTM_METHOD_CHECK(NSObject, _gtmDebugRemoveObserver:forKeyPath:); GTM_METHOD_CHECK(NSObject, _gtmDebugWillChangeValueForKey:); GTM_METHOD_CHECK(NSObject, _gtmDebugDidChangeValueForKey:); -GTM_METHOD_CHECK(NSArray, +GTM_METHOD_CHECK(NSArray, _gtmDebugArrayAddObserver:toObjectsAtIndexes:forKeyPath:options:context:); -GTM_METHOD_CHECK(NSArray, +GTM_METHOD_CHECK(NSArray, _gtmDebugArrayRemoveObserver:fromObjectsAtIndexes:forKeyPath:); #if GTM_PERFORM_KVO_CHECKS -GTM_METHOD_CHECK(NSObject, +GTM_METHOD_CHECK(NSObject, _gtmCheckAddObserver:forKeyPath:options:context:); -GTM_METHOD_CHECK(NSArray, +GTM_METHOD_CHECK(NSArray, _gtmCheckAddObserver:toObjectsAtIndexes:forKeyPath:options:context:); -GTM_METHOD_CHECK(NSObject, +GTM_METHOD_CHECK(NSObject, _gtmAccessInstanceVariablesDirectly); #endif // GTM_PERFORM_KVO_CHECKS @@ -503,23 +534,23 @@ GTM_METHOD_CHECK(NSObject, Class cls = Nil; if (debug) { cls = [NSObject class]; - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(addObserver:forKeyPath:options:context:), @selector(_gtmDebugAddObserver:forKeyPath:options:context:)); - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(removeObserver:forKeyPath:), @selector(_gtmDebugRemoveObserver:forKeyPath:)); - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(willChangeValueForKey:), @selector(_gtmDebugWillChangeValueForKey:)); - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(didChangeValueForKey:), @selector(_gtmDebugDidChangeValueForKey:)); cls = [NSArray class]; - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(addObserver:toObjectsAtIndexes:forKeyPath:options:context:), @selector(_gtmDebugArrayAddObserver:toObjectsAtIndexes:forKeyPath:options:context:)); - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(removeObserver:fromObjectsAtIndexes:forKeyPath:), @selector(_gtmDebugArrayRemoveObserver:fromObjectsAtIndexes:forKeyPath:)); } @@ -527,55 +558,55 @@ GTM_METHOD_CHECK(NSObject, cls = [NSObject class]; SwizzleMethodsInClass(cls, @selector(addObserver:forKeyPath:options:context:), - @selector(_gtmCheckAddObserver:forKeyPath:options:context:)); - SwizzleClassMethodsInClass(cls, - @selector(accessInstanceVariablesDirectly), + @selector(_gtmCheckAddObserver:forKeyPath:options:context:)); + SwizzleClassMethodsInClass(cls, + @selector(accessInstanceVariablesDirectly), @selector(_gtmAccessInstanceVariablesDirectly)); cls = [NSArray class]; - SwizzleMethodsInClass(cls, + SwizzleMethodsInClass(cls, @selector(addObserver:toObjectsAtIndexes:forKeyPath:options:context:), @selector(_gtmCheckAddObserver:toObjectsAtIndexes:forKeyPath:options:context:)); - + #endif // GTM_PERFORM_KVO_CHECKS [pool release]; } -- (void)_gtmDebugAddObserver:(NSObject *)observer - forKeyPath:(NSString *)keyPath +- (void)_gtmDebugAddObserver:(NSObject *)observer + forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context { _GTMDevLog(@"Adding observer %@ to %@ keypath '%@'", observer, self, keyPath); - [self _gtmDebugAddObserver:observer forKeyPath:keyPath + [self _gtmDebugAddObserver:observer forKeyPath:keyPath options:options context:context]; } - (void)_gtmDebugArrayAddObserver:(NSObject *)observer toObjectsAtIndexes:(NSIndexSet *)indexes - forKeyPath:(NSString *)keyPath + forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context { - _GTMDevLog(@"Array adding observer %@ to indexes %@ of %@ keypath '%@'", + _GTMDevLog(@"Array adding observer %@ to indexes %@ of %@ keypath '%@'", observer, indexes, self, keyPath); - [self _gtmDebugArrayAddObserver:observer + [self _gtmDebugArrayAddObserver:observer toObjectsAtIndexes:indexes - forKeyPath:keyPath + forKeyPath:keyPath options:options context:context]; } - (void)_gtmDebugRemoveObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath { - _GTMDevLog(@"Removing observer %@ from %@ keypath '%@'", + _GTMDevLog(@"Removing observer %@ from %@ keypath '%@'", observer, self, keyPath); [self _gtmDebugRemoveObserver:observer forKeyPath:keyPath]; } -- (void)_gtmDebugArrayRemoveObserver:(NSObject *)observer +- (void)_gtmDebugArrayRemoveObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath { - _GTMDevLog(@"Array removing observer %@ from indexes %@ of %@ keypath '%@'", + _GTMDevLog(@"Array removing observer %@ from indexes %@ of %@ keypath '%@'", indexes, observer, self, keyPath); - [self _gtmDebugArrayRemoveObserver:observer - fromObjectsAtIndexes:indexes + [self _gtmDebugArrayRemoveObserver:observer + fromObjectsAtIndexes:indexes forKeyPath:keyPath]; } @@ -605,9 +636,9 @@ GTM_METHOD_CHECK(NSObject, keyPath); } } - [self _gtmCheckAddObserver:observer - forKeyPath:keyPath - options:options + [self _gtmCheckAddObserver:observer + forKeyPath:keyPath + options:options context:context]; } @@ -628,8 +659,8 @@ GTM_METHOD_CHECK(NSObject, } [self _gtmCheckAddObserver:observer toObjectsAtIndexes:indexes - forKeyPath:keyPath - options:options + forKeyPath:keyPath + options:options context:context]; } @@ -637,7 +668,7 @@ GTM_METHOD_CHECK(NSObject, + (BOOL)_gtmAccessInstanceVariablesDirectly { // Apple has lots of "bad" direct instance variable accesses, so we // only want to check our code, as opposed to library code. - + // If this turns out to be slow, we may want to consider a cache to speed // things up. NSBundle *bundle = [NSBundle bundleForClass:self]; -- cgit v1.2.3