8
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?

Reid Main
  • 3,394
  • 3
  • 25
  • 42

2 Answers2

5

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)])
Gavin
  • 8,204
  • 3
  • 32
  • 42
  • 3
    And this is the link to the legacy documentation that you are referring to: [Object Oriented Programming and the Objective-C Programming Language 1.0](https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/OOPandObjC1/OOPandObjC1.pdf), page 62. (I had my answer almost finished :-) – Martin R Feb 19 '14 at 15:31
  • 1
    @MartinR Thank you for providing the link to the documentation. – Gavin Feb 19 '14 at 15:32
  • 2
    And btw, `Class = [NSString class]` compiles without warning for *any* protocol. - See also http://lists.cs.uiuc.edu/pipermail/llvmbugs/2013-March/027464.html. – Martin R Feb 19 '14 at 15:36
  • @MartinR True, but a lot of things that shouldn't be done ever will still compile :) – Gavin Feb 19 '14 at 15:38
  • Awesome work guys. I was searching the documentation for something about this but came up empty. Thanks for doing the legwork. – Reid Main Feb 19 '14 at 15:47
  • Oh also I just randomly picked NSString as the class to use. I know it doesn't conform to the protocol. I was more interested in why the compiler throws one as an error and one doesn't. I easily could have just set bah = nil and gotten the same result. – Reid Main Feb 19 '14 at 15:48
1

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.

Greg Parker
  • 7,972
  • 2
  • 24
  • 21