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

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.

Related

Obj-C, properties for everything

I have started work at a new company and one of the guidelines I have been told to adhere to by my team lead is to rarely use retain/release and instead rely on properties for memory management. I can see the appeal of keeping the code clear and leaving less room for mistakes but opening up the interfaces like this makes me uncomfortable. Generally speaking the architecture is very good but I have always been pedantic about closing up my classes to the outside world.
Is using properties like this an accepted design methodology in objective-c? Can anyone provide me with links or a clue where my new team may have picked up this strategy?
There is no need to expose properties to the entire world. In your implementation .m file you can add a little category to declare 'private' properties. E.g.
#import "Class.h"
#interface Class ()
#property (nonatomic, strong) NSDate *privateProperty
#end
#implementation Class
#synthesize privateProperty;
...
#end
Nothing in Objective-C is ever really private in strict terms, so I'd say this was good practice — it hides almost all of the retain/release stuff without requiring an ARC-compatible runtime and has the side effect of not requiring you to mention your instance variables in the header at all (though there are other ways to achieve that).
As a historical note, I think this was the first way to move instance variables out of the header — which is something permitted only by the 'new' runtime on iOS and 64bit Intel 10.6+ — so that may be a secondary reason why your team have settled upon it. Unless they've explicitly told you to make your classes transparent, they may actually be completely in agreement with your feeling (and the well accepted object oriented principle) that implementations should be opaque.
You don't have to declare your properties publicly. Using a class category or class extension, you can place your properties within the implementation.
For example:
// in AnObject.h
#interface AnObject : NSObject
#end
// in AnObject.m
#interface AnObject () // () is class extension, (foo) is a class category
#property (retain) NSString *foo;
#end
#implementation AnObject
#synthesize foo;
#end
For more information, see Apple's documentation.

What considerations determine whether to type and then cast to subtypes, or to use id?

If I have a class hierarchy in which subclasses require use of more specific types than those specified in the superclasses' ivars, is it better to declare the superclass ivar as id, or to type it and then cast where necessary in the subclasses?
For example I have a superclass which uses an ivar of type Thing:
#interface SuperClass {
Thing *_typedIvar; // OR
id anonIvar;
}
#property (nonatomic, retain, readwrite) Thing *_typedIvar;
#property (nonatomic, retain, readwrite) id anonIvar; // OR
Then in a subclass implementation I want to use a SubThing to get at its methodNotInThing
#interface SubClass : SuperClass {
}
#implementation {
- (void)aMethod {
SubThing *subtypedIvar = (SubThing *)self.typedIvar;
[subtypedIvar methodNotInThing];
// OR
[self.anonIvar methodNotInThing];
}
}
(I'm assuming here that the subclass has appropriately assigned a SubThing to the ivar).
I've used both approaches (in my thus far short time using ObjC), and am never quite resolved regarding which is best. I like the compiler checking offered by use of real types, along with being able to use dot syntax where appropriate. But the constant casting in subclasses gets pretty ugly, requires more code, and somehow tastes worse to me (which is hardly an argument, I suppose). However I like the fact in the typed version that the superclass in effect documents what subclasses should do with the ivar.
Which of the above would be the better approach, and why?
I would argue that using real types is better, despite the drawback of having your code littered with casts.
The programmer should be in control. Using id here is a bit careless.
Easier to follow, and therefore easier to debug.
While having casts everywhere may look messy, it forces you to be aware of what types you are expecting and again, this comes back to maintenance. It might work with id for right now, but if you have calls to id all over the place, how will you know why a particular one isn't working?

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.

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.