Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C runtime: What does declaring a variable of type Class (objc_class) conforming to a protocol mean?

Class bah = [NSString class];

id object = [bah new];

Compiles with absolutely no issues.

Class<NSSecureCoding> bah = [NSString class];

id object = [bah new];

Returns the error "No known class method for selector 'new'".

Why does the first instance understand that it can call the +new method defined on NSObject but the second instance does not?

like image 468
Reid Main Avatar asked Feb 19 '14 15:02

Reid Main


People also ask

What is the obj c runtime?

The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps. Objective-C runtime library support functions are implemented in the shared library found at /usr/lib/libobjc.


1 Answers

According to Apple's documentation:

Protocols can’t be used to type class objects. Only instances can be statically typed to a protocol, just as only instances can be statically typed to a class. (However, at runtime, both classes and instances respond to a conformsToProtocol: message.)

This is from old documentation, but there's nothing saying that it has since changed. But assuming it's still valid, based on that, you shouldn't be doing what you're doing. Instances of NSString may conform to that protocol, but you shouldn't be saying that the NSString Class object conforms to it.

As for why it gives you the error, I believe it's because when you're specifying the protocol, it will report an error for methods not in that protocol. For example, the following gives an error:

Class<NSSecureCoding> bah = [NSString class];
id object = [bah class];

But the following will compile (although it gives a warning that class is an instance method, not a class method):

Class<NSObject> bah = [NSString class];
id object = [bah class];

Also you'll notice that new is not defined in the NSObject protocol, only in the NSObject class.

So when you just specify Class, the compiler appears to do something similar to when you specify id in that it doesn't know the exact type, so it will let you call methods from any known type. But when you add the protocol to it, it will only let you call methods from that protocol.

If you want to ensure that whatever you assign to bah conforms to a particular protocol while just using Class, you could use the following:

if ([bah conformsToProtocol:@protocol(NSSecureCoding)])
like image 101
Gavin Avatar answered Nov 15 '22 04:11

Gavin