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

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.

Related

Who does what with protocols in objective-c?

Trying to understand protocols and their use... having a hard time of it. The more I read, the less I am able to even formulate questions about them. I've read the statement "a protocol is a contract" a hundred times, but it just doesn't click.
I "only" want to develop really simple apps, so assume that I would not myself create a protocol for any of my classes.
I do want to use Apple's Scenekit framework, for example, and understand that I am required to implement some methods to do this - for example the SCNSceneRendererDelegate. The compiler enforces this, and it knows to do that because in my header file I have inserted:
#interface AAPLGameViewController : UIViewController <SCNSceneRendererDelegate>
the bit between the angle brackets specifically.
For the prototypes of the functions I have to implement, I go look for a
#protocol
...
#end
section in the SCNSceneRendererDelegate header file.
But now I've come across some #protocol sections (e.g. in the UIApplication header file) that contain #properties!! I thought #protocol was only about implementing certain methods, what is a property doing there?
I also came across in one of the answers here that specifying a protocol name when creating an instance of an object allows me to use objects that I know nothing about. I would be very grateful to get a few simple practical examples of where this would be useful.
And finally, in Java, the counterpart to (Obj-C) #protocols are called interfaces. Is there a counterpart in Java to (Obj-C) #interface?
Thanks much, cheers.
Adhering to a protocol tells other classes that your class has a specific set of characteristics. Usually protocols are used to define what methods a specific class should have so that it can be the delegate of another class, meaning the class adopting the protocol is guaranteed to have defined the required methods that the delegate class will call in a callback. If the protocol defines a property, it simply means any classes adopting the protocol are expected to also have that property. For example:
#protocol MyProtocol <NSObject>
#required
#property (readonly) NSString *title;
#optional
- (void) someMethod;
#end
I can now define a method anywhere that takes an object conforming to MyProtocol and safely access the title property because it is guaranteed to exist for all classes adopting MyProtocol.
-(void)printTitleOfObject:(id<MyProtocol>)object {
NSLog(#"%#", object.title);
}
So even though id can be any object, since we know that it conforms to our protocol we know that it has the title property. When people say "a protocol is a contract", what they mean is even if we don't know specifically what class is adopting the protocol, we know it at least has the methods and properties listed as required in the protocol. Specifying a protocol for a class allows us to know some information about it, even if we don't know what class it is.
Apple has written documentation for protocols they've written, like the SCNSceneRendererDelegate you mentioned in your question.
But now I've come across some #protocol sections (e.g. in the
UIApplication header file) that contain #properties!! I thought
#protocol was only about implementing certain methods, what is a
property doing there?
Properties are methods. A property declaration is simply a declaration for a getter-setter method pair (or if a readonly property, just a getter method), and allows the compiler to turn a dot notation access into a call to this getter and setter. That's all a property is. How the getter/setter is implemented (whether manually implemented or synthesized), and whether it reflects an underlying value or not (or is computed from other things) are private implementation details of the getter/setter methods.

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.

Private classes in Objective C

I would like a pattern for a nested private class in Objective C.
Requirements are:
class will not be visible/accessible to other classes.
class can execute methods (i.e., not a C struct)
containing class members are visible/accessible to the nested class
Considering the comments, I am simplifying the requirements:
inner class may be accessible to other classes, but not visible (similar to using a category to hide private methods).
inner class does not have to be nested
Is it still not possible?
Objective-C has no notion of private classes or private instance variables in a formal declarative fashion.
Instead, visibility in Objective-C is entirely controlled by where you declare something. If it is in a header file, it can be imported by something else. If it is declared in an implementation file, it cannot (reasonably) be imported and, therefore, is effectively private to that compilation unit.
And by "it", I mean pretty much anything that can be declared; class, global, etc...
I.e. if you stick an #interface/#implementation pair for a class in a .m file, that class is effectively private to that compilation unit. Of course, without namespaces, make sure that class is uniquely named.
Consider this:
Foo.h:
#interface Foo: NSObject
... public interface
#end
Foo.m:
#interface __FooSupportClass: NSObject
... interface here ...
#end
#implementation __FooSupportClass
#end
#interface Foo()
#property(retain) __FooSupportClass *__fooSupport;
#end
#implementation Foo
#synthesize __fooSupport = fooSupport__;
... etc ...
#end
That gives you a private-by-visibility support class only available in your implementation with an instance variable and setter/getter methods on your class that are not visible outside the compilation unit either.
(Note that Objective-C has "instance variables", not "member variables". They are similar, but you'll be better off using the vocabulary of the language.)
Well you can have "semi-hidden" private methods. You can include an interface file that provides extension methods that is in the implementation file and then just implement the methods declared in there. I was curious about this before and asked a similar question.
Proper Objective-C Helper "Wannabe" Private methods?

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 >

Defining categories for protocols in Objective-C?

In Objective-C, I can add methods to existing classes with a category, e.g.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
Is it also possible to do this with protocols, i.e. if there was a NSString protocol, something like:
#interface <NSString> (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
I want to do this since I have several extensions to NSObject (the class), using only public NSObject methods, and I want those extensions also to work with objects implementing the protocol .
To give a further example, what if I want to write a method logDescription that prints an object's description to the log:
- (void) logDescription {
NSLog(#"%#", [self description]);
}
I can of course add this method to NSObject, but there are other classes that do not inherit from NSObject, where I'd also like to have this method, e.g. NSProxy. Since the method only uses public members of protocol , it would be best to add it to the protocol.
Edit: Java 8 now has this with "virtual extension methods" in interfaces: http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v4.pdf. This is exactly what I would like to do in Objective-C. I did not see this question earning this much attention...
Regards,
Jochen
Short answer: No.
Long answer: how would this work? Imagine you could add methods to existing protocols? How would this work? Imagine we wanted to add another method to NSCoding, say -(NSArray *) codingKeys; This method is a required method that returns an array of the keys used to encoding the object.
The problem is that there are existing classes (like, say NSString) that already implement NSCoding, but don't implement our codingKeys method. What should happen? How would the pre-compiled framework know what to do when this required message gets sent to a class that does not implement it?
You could say "we can add the definition of this method via a category" or "we could say that any methods added via these protocol categories are explicitly optional". Yes, you could do this and theoretically get around the problem I've described above. But if you're going to do that, you might as well just make it a category in the first place, and then check to make sure the class respondsToSelector: before invoking the method.
While it's true that you can't define categories for protocols (and wouldn't want to, because you don't know anything about the existing object), you can define categories in such a way that the code only applies to an object of the given type that has the desired protocol (sort of like C++'s partial template specialization).
The main use for something like this is when you wish to define a category that depends on a customized version of a class. (Imagine that I have UIViewController subclasses that conform to the Foo protocol, meaning they have the foo property, my category code may have need of the foo property, but I can't apply it to the Foo protocol, and if I simply apply it to UIViewController, the code won't compile by default, and forcing it to compile means someone doing introspection, or just screwing up, might call your code which depends on the protocol. A hybrid approach could work like this:
#protocol Foo
- (void)fooMethod
#property (retain) NSString *foo;
#end
#implementation UIViewController (FooCategory)
- (void)fooMethod {
if (![self conformsToProtocol:#protocol(Foo)]) {
return;
}
UIViewController<Foo> *me = (UIViewController<Foo>*) self;
// For the rest of the method, use "me" instead of "self"
NSLog(#"My foo property is \"%#\"", me.foo);
}
#end
With the hybrid approach, you can write the code only once (per class that is supposed to implement the protocol) and be sure that it won't affect instances of the class that don't conform to the protocol.
The downside is that property synthesis/definition still has to happen in the individual subclasses.
extObjC has the NEATEST stuff you can do with Protocols / Categories... first off is #concreteprotocol...
Defines a "concrete protocol," which can provide default implementations of methods within protocol.
An #protocol block should exist in a header file, and a corresponding #concreteprotocol block in an implementation file.
Any object that declares itself to conform to this protocol will receive its method implementations, but only if no method by the same name already exists.
MyProtocol.h
#protocol MyProtocol
#required - (void)someRequiredMethod;
#optional - (void)someOptionalMethod;
#concrete - (BOOL)isConcrete;
MyProtocol.m
#concreteprotocol(MyProtocol) - (BOOL)isConcrete { return YES; } ...
so declaring an object MyDumbObject : NSObject <MyProtocol> will automatically return YES to isConcrete.
Also, they have pcategoryinterface(PROTOCOL,CATEGORY) which "defines the interface for a category named CATEGORY on a protocol PROTOCOL". Protocol categories contain methods that are automatically applied to any class that declares itself to conform to PROTOCOL." There is an accompanying macro you also have to use in your implementation file. See the docs.
Last, but NOT least / not directly related to #protocols is
synthesizeAssociation(CLASS, PROPERTY), which "synthesizes a property for a class using associated objects. This is primarily useful for adding properties to a class within a category. PROPERTY must have been declared with #property in the interface of the specified class (or a category upon it), and must be of object type."
So many of the tools in this library open (way-up) the things you can do with ObjC... from multiple inheritance... to well, your imagination is the limit.
It isn't really meaningful to do so since a protocol can't actually implement the method. A protocol is a way of declaring that you support some methods. Adding a method to this list outside the protocol means that all "conforming" classes accidentally declare the new method even though they don't implement it. If some class implemented the NSObject protocol but did not descend from NSObject, and then you added a method to the protocol, that would break the class's conformance.
You can, however, create a new protocol that includes the old one with a declaration like #protocol SpecialObject <NSObject>.
I think you may be mixing up terms here and there. Extensions, Categories, Protocols, Interfaces and Classes are all different things in Objective-C. In The Objective-C 2.0 Language Apple describes the differences very well, including the benefits and drawbacks to using categories and extensions.
If you think about it, what is a "Category" or "Extension" in the conceptual sense? It's a way of adding functionality to a Class. In Objective-C, protocols are designed to have no implementation. Therefore, how would you add or extend the implementation of something that doesn't have implementation to begin with?
if you're already writing a category, why not just add in the protocol definition in the header right after the category definition?
i.e.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
#protocol MyExtendedProtocolName <NSString>
//Method declarations go here
#end
this way any class that imports the category header will also get the protocol definition, and you can add it into your class..
#interface MyClass <OriginalProtocol,MyExtendedProtocolName>
also, be careful when subclassing NSString, it's a cluster and you may not always get the behaviour you're expecting.
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
Defining the methods you want to add as #optional on a protocol.
Making the objects you want to extend conform to that protocol.
Copying those methods into those objects at runtime.
Check out the link for the full details.