What is the different between an id and NSObject in Objective C? - 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.

Related

RLMArray property declaration syntax

When declaring an RLMArray, what is the significance of the second set of brackets? Realm is the only place I've seen this used.
#property NSArray<NSDictionary*> *dictionaries; // I understand this (and it's wonderful!)
#property NSDictionary<NSString*, NSArray<NSString*>*> *dictionaryOfArraysOfStrings; // No problem with this either
#property RLMArray<Object*><Object> *objects; // What is <Object> for?
The two sets of angle brackets are for Objective-C generics and protocols respectively. Objective-C generics lets the compiler know that methods like -[RLMArray firstObject] return the specific type of object that the array contains, rather than any possible RLMObject subclass. Sadly this extra type information is erased at runtime, so Realm has no way to tell from the use of Objective-C generics alone in the property declaration what type of object the array contains. This is where the protocol conformance comes in. The protocol that a property conforms to is available to Realm at runtime, and so is used to inform Realm of the object type that your RLMArray property will contain. Realm provides the RLM_ARRAY_TYPE macro to declare a protocol of the same name as a model class, so it is easy to miss that a protocol is involved.

Why doesn't Xcode provide autocompletion for dot-notated properties on objects of type id<protocol>?

Given this protocol definition:
#protocol MyProtocol <NSObject>
#property (nonatomic, strong) NSString *someProperty;
#end
Why will Xcode gladly offer autocompletion for this statement:
id<MyProtocol> thing = [ThingManager currentThing];
[thing someProperty]; // Xcode offered autocompletion here
But it doesn't offer autocompletion when I try to access the same property using dot-notation:
id<MyProtocol> thing = [ThingManager currentThing];
thing.someProperty; // Xcode claimed there were
// "No completions" available
// after the period
Because id is a base type, Xcode and CLANG are uneasy about providing dot-syntax access against it because dot syntax is just syntactic sugar for a method call to an associated setter or getter in a normal object, but id has no defined method members. Looking at it from the C side of things, id is a typedef for a struct pointer that the compiler cannot see the members of, which means it cannot access them (never mind the fact that you would need to dereference id before dot-access would make any semantic sense).
Back to the Objective-C side of things, protocols don't actually add methods or properties to the classes that claim to implement them, rather they serve as a specifier to other classes that an object that conforms to a given protocol implements a series of methods. As for the method-syntax being completed, Xcode pools all of the given methods of all the files imported into a given .m file because, an object of type id can receive any message*
*of course, it can receive the message, but it'll still crash if it's unimplemented.
This is kind of a tangential answer, and a thought experiment.
But before that, I'll note that you could get your property autocomplete by skipping id, like this:
NSObject<MyProtocol> *thing;
thing.▮
But assuming you don't want the entire list of NSObject methods gumming up your completion, you could do something like
EmptyClass<MyProtocol> *thing = [ThingManager currentThing];
// completion list will be (close) to only the protocol props
thing.▮
EmptyClass serves a similar "OK, no promises!" role that id does, but autocomplete likes it. Here's EmptyClass:
NS_ROOT_CLASS
#interface EmptyClass
#end
#implementation EmptyClass
+ (void)initialize {} // required
#end
Mind you, the object in thing is not actually rooted on EmptyClass (can't be), so this is high fakery. However, it
vastly underpromises what thing can actually do.
doesn't (can't!) instantiate an EmptyClass object.
So why not? If you try really hard, you can cause problems like
EmptyClass *nooooo = [[NSClassFromString(#"EmptyClass") alloc] init];
which will immediately exception. But not really a tricky bug to avoid.
A gotcha wouldn't surprise me, but I don't know one right now. Please, leave a comment if you do.

Minutia on Objective-C Categories and Extensions

I learned something new while trying to figure out why my readwrite property declared in a private Category wasn't generating a setter. It was because my Category was named:
// .m
#interface MyClass (private)
#property (readwrite, copy) NSArray* myProperty;
#end
Changing it to:
// .m
#interface MyClass ()
#property (readwrite, copy) NSArray* myProperty;
#end
and my setter is synthesized. I now know that Class Extension is not just another name for an anonymous Category. Leaving a Category unnamed causes it to morph into a different beast: one that now gives compile-time method implementation enforcement and allows you to add ivars. I now understand the general philosophies underlying each of these: Categories are generally used to add methods to any class at runtime, and Class Extensions are generally used to enforce private API implementation and add ivars. I accept this.
But there are trifles that confuse me. First, at a hight level: Why differentiate like this? These concepts seem like similar ideas that can't decide if they are the same, or different concepts. If they are the same, I would expect the exact same things to be possible using a Category with no name as is with a named Category (which they are not). If they are different, (which they are) I would expect a greater syntactical disparity between the two. It seems odd to say, "Oh, by the way, to implement a Class Extension, just write a Category, but leave out the name. It magically changes."
Second, on the topic of compile time enforcement: If you can't add properties in a named Category, why does doing so convince the compiler that you did just that? To clarify, I'll illustrate with my example. I can declare a readonly property in the header file:
// .h
#interface MyClass : NSObject
#property (readonly, copy) NSString* myString;
#end
Now, I want to head over to the implementation file and give myself private readwrite access to the property. If I do it correctly:
// .m
#interface MyClass ()
#property (readwrite, copy) NSString* myString;
#end
I get a warning when I don't synthesize, and when I do, I can set the property and everything is peachy. But, frustratingly, if I happen to be slightly misguided about the difference between Category and Class Extension and I try:
// .m
#interface MyClass (private)
#property (readwrite, copy) NSString* myString;
#end
The compiler is completely pacified into thinking that the property is readwrite. I get no warning, and not even the nice compile error "Object cannot be set - either readonly property or no setter found" upon setting myString that I would had I not declared the readwrite property in the Category. I just get the "Does not respond to selector" exception at runtime. If adding ivars and properties is not supported by (named) Categories, is it too much to ask that the compiler play by the same rules? Am I missing some grand design philosophy?
Class extensions were added in Objective-C 2.0 to solve two specific problems:
Allow an object to have a "private" interface that is checked by the compiler.
Allow publicly-readable, privately-writable properties.
Private Interface
Before Objective-C 2.0, if a developer wanted to have a set of methods in Objective-C, they often declared a "Private" category in the class's implementation file:
#interface MyClass (Private)
- (id)awesomePrivateMethod;
#end
However, these private methods were often mixed into the class's #implementation block (not a separate #implementation block for the Private category). And why not? These aren't really extensions to the class; they just make up for the lack of public/private restrictions in Objective-C categories.
The problem is that Objective-C compilers assume that methods declared in a category will be implemented elsewhere, so they don't check to make sure the methods are implemented. Thus, a developer could declare awesomePrivateMethod but fail to implement it, and the compiler wouldn't warn them of the problem. That is the problem you noticed: in a category, you can declare a property (or a method) but fail to get a warning if you never actually implement it -- that's because the compiler expects it to be implemented "somewhere" (most likely, in another compilation unit independent of this one).
Enter class extensions. Methods declared in a class extension are assumed to be implemented in the main #implementation block; if they're not, the compiler will issue a warning.
Publicly-Readable, Privately-Writeable Properties
It is often beneficial to implement an immutable data structure -- that is, one in which outside code can't use a setter to modify the object's state. However, it can still be nice to have a writable property for internal use. Class extensions allow that: in the public interface, a developer can declare a property to be read-only, but then declare it to be writable in the class extension. To outside code, the property will be read-only, but a setter can be used internally.
So Why Can't I Declare a Writable Property in a Category?
Categories cannot add instance variables. A setter often requires some sort of backing storage. It was decided that allowing a category to declare a property that likely required a backing store was A Bad Thing™. Hence, a category cannot declare a writable property.
They Look Similar, But Are Different
The confusion lies in the idea that a class extension is just an "unnamed category". The syntax is similar and implies this idea; I imagine it was just chosen because it was familiar to Objective-C programmers and, in some ways, class extensions are like categories. They are alike in that both features allow you to add methods (and properties) to an existing class, but they serve different purposes and thus allow different behaviors.
You're confused by the syntactic similarity. A class extension is not just an unnamed category. A class extension is a way to make part of your interface private and part public — both are treated as part of the class's interface declaration. Being part of the class's interface, an extension must be defined as part of the class.
A category, on the other hand, is a way of adding methods to an existing class at runtime. This could be, for example, in a separate bundle that is only loaded on Thursdays.
For most of Objective-C's history, it was impossible to add instance variables to a class at runtime, when categories are loaded. This has been worked around very recently in the new runtime, but the language still shows the scars of its fragile base classes. One of these is that the language doesn't support categories adding instance variables. You'll have to write out the getters and setters yourself, old-school style.
Instance variables in categories are somewhat tricky, too. Since they aren't necessarily present when the instance is created and the initializer may not know anything about them, initializing them is a problem that doesn't exist with normal instance variables.
You can add a property in a category, you just can't synthesize it. If you use a category, you will not get a compile warning because it expects the setter to be implemented in the category.
Just a little clarification about the REASON for the different behavior of unnamed categories (now known as Class Extensions) and normal (named) categories.
The thing is very simple. You can have MANY categories extending the same class, loaded at runtime, without the compiler and linker ever knowing. (consider the many beautiful extensions people wrote to NSObject, that add it functionality post-hoc).
Now Objective-C has no concept of NAME SPACE. Therefore, having iVars defined in a named category could create a symbol clash in runtime. If two different categories would be able to define the same
#interface myObject (extensionA) {
NSString *myPrivateName;
}
#end
#interface myObject (extensionB) {
NSString *myPrivateName;
}
#end
then at the very least, there will be memory overrun at runtime.
In contradiction, Class extensions have NO NAME, and thus there can be only ONE. That's why you can define iVars there. They are assured to be unique.
As for the compiler errors and warnings related to categories and class extensions + ivars and property definitions, I have to agree they are not so helpful, and I spent too much time trying to understand why things compile or not, and how they work (if they work) after they compile.

id and Delegate Usage in Obj-C

I am wondering what the following line of code is doing:
#property (assign, nonatomic) id <CoursePlannerDelegate> delegate;
Namely I am wondering about this portion of the line:
id <CoursePlannerDelegate> delegate;
It also shows up in other places:
#interface CategoryAddViewController : UIViewController {
UITextField *nameField, *weightField;
double maxWeight; //The maximum weight that can be allocated to this Category (max value of 100)
id <CategoryAddDelegate> delegate; //A Course Planner TVC
}
JustSid's answer is spot-on, but just a bit more clarification:
Compared to other OO languages, Objective-C lacks interfaces. Instead, Objective-C uses protocols, marked by the #protocol directive.
The id data type is an anonymous object. It's an Objective-C object -- that much is certain to the compiler. The compiler knows how much space to reserve for a pointer to the object, but it doesn't know at compile time if it's an NSString, a UIViewController, or what.
So, when you use the id type, you can specify (in angle brackets) a protocol that that anonymous object should adhere to.
In your code above, when compiling, the compiler will check any object you set to the delegate of CategoryAddViewController and double-check that you've implemented any required methods defined in the protocol.
Summed up, using the angle brackets when you use the id type will help the compiler tell you when you're doing something stupid.
All of this is for compile time -- if you need to be 100% paranoid at run time as well, you can use conformsToProtocol:#protocol(foo) to test for compliance (I believe this is a method on any NSObject).
It makes sure that you pass an Objective-C object that conforms to the given protocol. Thats it, if it doesn't, the compiler will throw a warning but nothing more.

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.