Objective-C Class keyword and Protocols - objective-c

What does it mean in Objective-C if you try to mix Class and Protocol? I'm trying to get the complier to warn me at compiler time if a class doesn't conform to a protocol. For example:
#protocol FLLiveDataProtocol <NSObject>
...
#end
- (id)initWithDataPath:(NSString *)path usingDataClassFactory:(Class<FLLiveDataProtocol>)dataFactoryClass;
However, I get all kind of interesting issues when I try this. First, it doesn't trigger a compiler error if you pass in a class that doesn't conform to the protocol, second you will get errors such as "No know class method for selector alloc" if you try to do [[dataFactoryClass] alloc] init] even through the protocol conforms to NSObject.
I haven't seen many examples of people trying to mix protocol's and the Class keyword (I should say Typedef -- thanks Nikolai).
I know I can use conformsToProtocol to check at runtime, but it would be nice if I could get this to check at compile time.

There's no static type information for class objects in Objective-C (see this question), so there's no way to express the need for a class to conform to a protocol.
Side note: Class is not a keyword but a typedef in objc.h:
typedef struct objc_class *Class;

second you will get errors such as "No know class method for selector
alloc" if you try to do [[dataFactoryClass] alloc] init] even through
the protocol conforms to NSObject.
The reason for this is that neither your protocol or the NSObject protocol declare +alloc. You could fix this by adding an +alloc method (or some other class method that returns a new instance) to your protocol declaration.

Related

Create an instance from a Class that conforms to a Protocol

I'm trying to accomplish something like the following:
- (id<SomeProtocol>)instanceFromClass:(Class<SomeProtocol>)cls
{
return [[cls alloc] initUsingSomeConstructorDefinedInProtocolWithValue:_value];
}
However, I'm getting a No Known class method for selector 'alloc' error. How may I specify in my signature that I want to receive a class that conforms to a protocol? Or, if that part is correct, how may I create an instance from that argument using a constructor defined in the specified protocol?
Not sure why the compiler complains but you can fix by casting your parameter back to Class
- (id<SomeProtocol>)instanceFromClass:(Class<SomeProtocol>)cls
{
return [[(Class)cls alloc] initUsingSomeConstructorDefinedInProtocolWithValue:_value];
}
while still getting you the type checking you want for the parameter as hinted at in this SO answer: Declare an ObjC parameter that's a Class conforming to a protocol
Your use of the protocol is 'fine'. The issue is that the cls parameter is tagged as a class which conforms to a protocol that defines instance methods (the init method). This doesn't tell the compiler that the +alloc method is available because that is a class method on NSObject.
You can add the +alloc method to the protocol. Or you can do some casting to tell the compiler to trust you.
+ alloc is a method defined by the top level class NSObject. When you have a class like Class <SomeProtocol>, the compiler only knows that this is some class and it implements SomeProtocol but it cannot know if that is a subclass of NSObject or not, since in Obj-C you can define own top-level classes that don't inherit from NSObject (not that this is generally a good idea but it is possible).
There is a special "hack" in the compiler that in case the type is just Class, the compiler will always assume that it is a subclass of NSObject and would only fail at runtime in case it isn't. But this hack only works for the exact type Class and not for Class <SomeProtocol> which is a distinct type.
So what you can do is to either cast to Class, so the hack works again:
[[(Class)cls alloc] ...]
or you can also do that
[[cls.class alloc] ...]
in case that cls will be a subclass of NSObject at runtime because then it will have a + class method.
Note that if I call instanceFromClass: with a class, that does implement SomeProtocol but is no subclass of NSObject and also does not implement a + alloc method, both methods above will fail at runtime and the app will crash.

What does a variable defined as `Class<SomeProtocol> myClass` mean?

I am used to seeing things like id<NSCopying> myVar or MyObject<NSCopying> myVar, where we are stating that the variable in question can happily have NSCopying methods called on it without the compiler throwing a wobbly.
But I recently spotted some code that defined a variable like this:
Class<NSCopying> myClass;
I was wondering what this actually means as it seems subtly different from the top two examples. It seems like we're saying that the variable myClass can happily accept method calls from NSCopying - but having a class type able to accept these instance variable methods doesn't seem to make much sense.
It has occurred to me that variables of type class are technically objects themselves which is probably confusing me or the compiler (probably me!).
So I guess I'm asking:
What does something like Class<NSCopying> myClass; actually mean
How does Class<NSCopying> myClass; differ to something like id<NSCopying> myVar
Where could something like Class<NSCopying> myClass; be meaningfully used?
Notes:
I am just using NSCopying as an example and isn't integral to my use case
Wherever I refer to Class I mean the Obj-C keyword Class for declaring variables that are of type Class. I am not using this as a generic term for any class type.
Well I think it might mean that Class <NSCopying> myClass points to a class that implements NSCopying protocol. It can be useful if protocol has class method declarations and you want to call them.
For example:
#protocol NSSecureCoding <NSCoding>
#required
// The Secure Coding Guide should be consulted when writing methods that decode data.
+ (BOOL)supportsSecureCoding;
#end
id <NSCopying> myVar
Using id you can supply an instance of any type of class (so long as it implements the protocol, or you cast it to make the compiler trust you).
Class <NSCopying> myClass
Using Class means you can only supply a Class, not an instance.
Say you wanted your app to be configurable. Say you had a number of classes which offered a number of different features, but you didn't care about inheritance they had, just how to create and configure them. You could use a protocol that the class has to conform to and offer a method where the classes can be registered. Then you can instantiate those classes using the defined protocol without knowing anything else about the class.
Class<ProtocolName> is the type of a variable pointing to a class object with a meta class that conforms to ProtocolName. In other words: The class implements the methods from ProtocolName with class methods.
Example: NSCopying contains one required method:
#protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
#end
Class<NSCopying> means that there is a method
+ (id)copyWithZone:(NSZone *)zone;
in the class being pointed to. That is true for all NSObject derived classes and useful for using class objects as dictionary keys. See the documentation.

Does objective c support private inheritance of protocol

Can a protocol can be inherited privately so that in next inheritance level this should not be accessed ?
Objective-C has no “private inheritance” (or “private conformance”) the way C++ does.
You can conform to a protocol without advertising your conformance in your header file. For example, you can conform to NSCoding “secretly” if you put this above your #implementation statement in your .m file:
#interface MyObject () <NSCoding>
#end
That declares a class extension that adds the NSCoding protocol to the MyObject class.
However, anyone (including a subclass) can ask whether you adopt the protocol:
[[MyObject class] conformsToProtocol:#protocol(NSCoding)]
// returns YES
[[MySubObject class] conformsToProtocol:#protocol(NSCoding)]
// also returns YES, if MySubObject is a subclass of MyObject
and anyone can send an NSCoding message to a MyObject by casting the object first:
[(id<NSCoding>)someObject encodeWithCoder:someCoder]
And if you make a subclass of MyObject, and your subclass also declares that it conforms to NSCoding, then it almost certainly needs to call [super encodeWithCoder:] from its own encodeWithCoder: method.
No, it's not possible because of the language design.
Moreover, as any method could be override, you can't ever be sure that your called method if from the right class.
There may be some hack which permit to directly invoke the method you want, but it's not that easy and may even not be possible.
Protocol or otherwise, there is no way to stop methods being overridden by subclasses
[Source]

What is the different between an id and NSObject in Objective C?

What is the different between this:
id:
#import <objc/Object.h>
#interface Forwarder : Object
{
id something;
}
NSObject:
#import <objc/Object.h>
#interface Forwarder : Object
{
NSObject *something;
}
Thz u.
This Greg MILLER's blog post from the unixjunkie blog sums up the differences
Some extracts:
There's often confusion about the difference between the following three declarations in Objective-C:
id foo1;
NSObject *foo2;
id<NSObject> foo3;
The first one is the most common.
It simply declares a pointer to some Objective-C object (see /usr/include/objc/objc.h). id gives the compiler no information about the actual type of the object, so the compiler cannot do compile-time type checking for you.
Just because we know that an id is an Objective-C object does not mean that it points to an object that derives from NSObject, or that it even has common methods like retain and release.
One solution is to statically type our variable using NSObject* as shown in number 2 above.
This gives the compiler information about the class of the object pointed to by foo2 so the compiler can warn if you send a message to foo2 that an NSObject doesn't respond to. This means you can safely call retain, release, description, etc., but the compiler will warn if you call length or count or anything that an NSObject doesn't respond to.
Declaring an object as id<NSObject> tells the compiler that you don't care what type the object is, but you do care that it conforms to the specified NSObject protocol**.
** the protocol (#protocol) named NSObject. There is also a class named NSObject that does indeed conform to the NSObject protocol, but they are two different thing
The compiler will ensure that all objects you assign to that pointer conform to the required protocol.
A pointer typed like this can safely hold any NSObject (because NSObject conforms to the NSObject protocol), but it could also hold any NSProxy, because NSProxy also conforms to the NSObject protocol.
In english, the declaration id<NSObject> foo3; says "foo3 is a pointer to an object of any type that behaves like an NSObject".
This is very powerful, convenient, and expressive. In reality, we often don't care what type an object is, we just care that it responds to the messages that we want to send it (e.g., retain, release).
If you don't want (or can't have) any type checking, then use a plain id. This is very common for return types on methods that don't know the type of object they're returning (e.g., +alloc). It is also common to declare delegates to be type id, because delegates are generally checked at runtime with respondsToSelector:, and they usually aren't retained.
However, if you do want compile-time type checking, you must decide between the second and third cases. Well, let me just help you out—you want the third case! :-) I've very, very, VERY rarely seen a situation where NSObject * worked but id would not. And using the protocol form has the advantage that it will work with NSProxys.
The practical difference is that you do not need to typecast an id, but you usually need to typecast an NSObject * to something before using it. NSObject is the base class that almost all other classes are derived from where id is more of a language keyword.
An id responds to any method without a compiler warning; NSObjects only respond without warning to methods defined in NSObject, including the NSObject protocol.

What are the angle brackets "<…>" in an Obj-C class interface for?

Can anyone tell me what the angle brackets <...> in an Objective-C class interface do? Like this one (from http://snipt.net/robhawkes/cocoa-class-interface):
#interface MapMeViewController : UIViewController <CLLocationManagerDelegate,
MKReverseGeocoderDelegate, MKMapViewDelegate, UIAlertViewDelegate> { ... }
From my view they look like some sort of type declaration (considering my previous experience in PHP and JavaScript), like we're making sure MapMeViewController is a CLLocationManagerDelegate, MKReverseGeocoderDelegate, MKMapViewDelegate, or UIAlertViewDelegate
Documentation about the #interface syntax don't seem to mention this.
The angle brackets in a class interface definition indicates the protocols that your class is conforming to.
A protocol is almost like an interface in Java or C#, with the addition that methods in an Objective-C protocol can be optional.
Additionaly in Objective-C you can declare a variable, argument or instance variable to conform to several protocols as well. Example
NSObject<NSCoding, UITableViewDelegate> *myVariable;
In this case the class must be NSObject or a subclass (only NSProxy and its subclasses would fail), and it must also conform to both NSCoding and UITableViewDelegate protocols.
In Java or C# this would only be possible by actually declaring said class.
The angle brackets indicate a protocol. They're analogous to interfaces in other languages.
You can also use them in code like a cast to tell the complier to expect an object that conforms to a particular protocol.
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.noteFetcher sections] objectAtIndex:section];
Apple documentation reports the use of brackets; see The Objective-C Programming Language on the chapter 4, on "Adopting a Protocol".
Adopting a protocol is similar in some ways to declaring a superclass. Both assign methods to the class. The superclass declaration assigns it inherited methods; the protocol assigns it methods declared in the protocol list. A class is said to adopt a formal protocol if in its declaration it lists the protocol within angle brackets after the superclass name:
#interface ClassName : ItsSuperclass < protocol list >
Categories adopt protocols in much the same way:
#interface ClassName ( CategoryName ) < protocol list >