How do I get my iPhone-application to load protocols dynamicly?
I'm writing an RPC implementation with proxy objects (think NSDistantObject). While doing this, we generate header-files (both DTO:s and protocols) directly from the server implementation. I'm creating objects dynamically in runtime, but I've 开发者_如何学编程encountered a specific problem.
When encountering an object, I have the name as a string, and I from there figure out what to do with it. My problem appears when I attempt to "query" the system for a protocol that isn't used anywhere in the code. The header-file is there, even #import
:ed.
Some examples...
This works great:
Protocol *protocol = NSProtocolFromString(@"UIApplicationDelegate"); // Returns a protocol
If I take one of my own protocols and specifies that my application delegate should comply to it, it also works without any problems:
@interface ApplicationDelegate : NSObject <UIApplicationDelegate, ACMyCustomProtocol> {
}
// Implementation...
Protocol *protocol = NSProtocolFromString(@"ACMyCustomProtocol"); // Returns a protocol
But if I ask for a protocol, that no class in my project conforms to, I get nil
:
Protocol *protocol = NSProtocolFromString(@"ACMyCustomProtocolNotMentionedAnywhere"); // Returns nil
I've tried changing the build configuration (figured that Xcode maybe strips the unused code when building) with no luck. Also tried Protocol *objc_getProtocol(const char *name)
without luck.
Edit:
I got a tip from a kind user on the developer forums, unfortunately, it probably means I'm out of luck.
The Objective-C Programming Language: Protocols
Protocols that are declared but not used (except for type checking as described below) aren’t represented by Protocol objects at runtime.
Since your protocols are #import
ed, simply doing a @protocol(MyProtocolName)
somewhere in the compiled code should be enough to make sure the Protocol
object exists at runtime. Maybe a good way to do this is to create a static NSDictionary
that maps from known protocol names to Protocol
objects. Basically you'd be reimplementing NSProtocolFromString
for your known protocols, but it guarantees that those protocol objects will be compiled. I.e. something like:
+ (Protocol)remoteProtocolForName:(NSString *)name
{
static NSDictionary *dict = nil;
if (!dict)
{
dict = [[NSDictionary alloc] initWithObjectsAndKeys:
@protocol(Foo), @"Foo",
...];
}
return [dict objectForKey:name];
}
It occurs to me now that I'm not sure you can store Protocol
s in an NSDictionary
...
精彩评论