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

StackOverflow https://stackoverflow.com/questions/21884248

  •  13-10-2022
  •  | 
  •  

Question

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?

Was it helpful?

Solution

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)])

OTHER TIPS

Class<NSSecureCoding> is an object that responds to the class methods of protocol NSSecureCoding. Protocol NSSecureCoding does not declare method +new, so you can't call it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top