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.
What do you mean it is not valid? Do you get a compile error?
Objective-C supports dynamic typing for objects by default. You should be able to call any method on any object in Objective-C, even if the compiler can't guarantee from the static type that that object supports that method.
I think you need to cast them to
NSObject *
, since that's where the KVO methods are (not inNSObject
protocol).Just let me add that the approach you outline with ...
... will of course not be able to supress your compile-time warnings, since the class "foo" will only get calculated at run-time. So even though you as the programmer can plainly see from the code that "foo" will end up being the class "MyClass", this is not clear to the compiler, and so if "MyClass" has a method "myMethod:" you will still get a compiler warning if you send that message to an object declared as "foo".
I'm guessing you realise this, but it's better to make it clear why that approach won't solve your problem.
If you code like this:
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:
The compiler will give you a warning:
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:
That will compile fine too, as in this case you're using the class NSObject.
Related links: