I have several dataSources I use for one UIViewController. My view controller uses KeyValue Observing in order to follow the state of certain properties at runtime. When I swap dataSources, I need to stop observing those properties. The problem is, I'm not sure of the class of the dataSource at runtime, therefor something like this is not valid:
if (aDataSource != dataSource) {
// Ensure we stop observing the existing dataSource, otherwise bad stuff can happen.
[dataSource removeObserver:self forKeyPath:@"someKeyPath"]; // not valid, compiler doesn't know what class dataSource is.
[dataSource release];
dataSource = [aDataSource retain];
}
The compiler needs a concrete class in order to know the object's interface. How can I grab the class of dataSource in this particular case, and then typcast the dataSource for the removeObserver:forKeyPath: selector above? I prefer something dynamic/smarter than caching the name of the class in an NSString instance and referring to that whenever I switch. Meaning, I could always do something like:
NSString *lastDataSource = @"MyClass";
Class foo = [NSClassFromString(lastDataSource)];
Thanks.
If you code like this:
id foo = ...;
[foo removeObserver:self forKeyPath:@"someKeyPath"];
The compiler will be fine with it as objects with type id
accepts any message (as long the signature is known to the compiler).
Now if you have:
id<NSObject> foo = ...;
[foo removeObserver:self forKeyPath:@"someKeyPath"];
The compiler will give you a warning:
warning: '-removeObserver:forKeyPath:' not found in protocol
This is because you're referring to the protocol NSObject not to the NSObject class where the KVO methods are defined.
But if you have:
NSObject* foo = ...;
[foo removeObserver:self forKeyPath:@"someKeyPath"];
That will compile fine too, as in this case you're using the class NSObject.
Related links: