Understand Objective-C runtime - objective-c

I have read about how Objective-C runtime works, so please comment if I misunderstood something.
Let's say I have class called Person. That class may or not have method getSex.
Person *p = [[Person alloc]init];
Here the memory is allocated for Person instance (isa is created also which points to class Person), init is used to initialize Person ivar's
[p getSex];
Here objc_msgSend(Person,#selector(getSex) is called on Person class.
If Person class not have such method the runtime look for that method in Person root class and so on. When the method is found IMP is called which is a pointer to method block code. Then the method is executed.
Is that correct ?

Yes, everything is correct, except the behavior of init may or may not initialize all its member variables such that the accessors return valid results, although it is reasonable to guess that it initializes properties unless told otherwise.

There's one piece that's slightly off.
The call will actually be one of these three:
objc_msgSend(p, #selector(getSex))
objc_msgSend_fpret(p, #selector(getSex))
objc_msgSend_stret(p, #selector(getSex))
One difference here is that the first argument is to the object and not to the class.
Also, since you didn't share what the getSex method returns, it's not possible for us to know whether it will be one of the fpret/stret versions or not. If the method returns a double (on certain platforms), the fpret version will be used. If the method returns a structure value (on certain platforms), then the stret version will be used. All others will use the standard version. All of this is platform dependent in many different ways.
As the others said, allocation will create an object with all instance variables set to 0/NULL and a valid isa pointer as well. Initialization methods may or may not update the instance variables with something meaningful.

Related

Do Objective-C objects get their own copies of instance methods?

I'm new to Objective-C and was wondering if anyone could provide any information to clarify this for me. My (possibly wrong) understanding of object instantiation in other languages is that the object will get it's own copies of instance variables as well as instance methods, but I'm noticing that all the literature I've read thus far about Objective-C seems to indicate that the object only gets copies of instance variables, and that even when calling an instance method, program control reverts back to the original method defined inside the class itself. For example, this page from Apple's developer site shows program flow diagrams that suggest this:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Also in Kochan's "Programming in Objective-C", 6th ed., pg. 41, referring to an example fraction class and object, the author states that:
"The first message sends the setNumerator: message to myFraction...control is then sent to the setNumerator: method you defined for your Fraction class...Objective-C...knows that it's the method from this class to use because it knows that myFraction is an object from the Fraction class"
On pg. 42, he continues:
"When you allocate a new object...enough space is reserved in memory to store the object's data, which includes space for its instance variables, plus a little more..."
All of this would seem to indicate to me that there is only ever one copy of any method, the original method defined within the class, and when calling an instance method, Objective-C simply passes control to that original copy and temporarily "wires it" to the called object's instance variables. I know I may not be using the right terminology, but is this correct? It seems logical as creating multiple copies of the same methods would be a waste of memory, but this is causing me to rethink my entire understanding of object instantiation. Any input would be greatly appreciated! Thank you.
Your reasoning is correct. The instance methods are shared by all instances of a class. The reason is, as you suspect, that doing it the other way would be a massive waste of memory.
The temporary wiring you speak of is that each method has an additional hidden parameter passed to it: a pointer to the calling object. Since that gives the method access to the calling object, then it can easily access all of the necessary instance variables and all is well. Note that any static variable exists in only a single instance as well and if you are not aware of that, unexpected things can happen. However, regular local variables are not shared and are recreated for each call of a method.
Apple's documention on the topic is very good so have a look for more info.
Just think of a method as a set of instructions. There is no reason to have a copy of the same method for each object. I think you may be mistaken about other languages as well. Methods are associated with the class, not individual objects.
Yes, your thinking is more or less right (although it's simpler than that: behind the scenes in most such languages methods don't need to be "wired" to anything, they just take an extra parameter for self and insert struct lookups before references to instance variables).
What might be confusing you is that not all languages work this way, in their implementations and semantically. Object-oriented languages are (very roughly) divided into two camps: class-based, like Objective-C; and prototype-based, like Javascript. In the second camp of languages, a method or procedure really is an object in its own right and can often be assigned directly to an object's instance variables as well - there are no classes to lookup methods from, only objects and other objects, all with the same first-class status (this is an oversimplification, good languages still allow for sharing and efficiency).

Objective-C, ownership and class methods

First off, I'm a Objective-C newbie. :)
I've learned that anything that starts with alloc, new, and copy, gives the caller ownership of the returned object. Does this also apply to class methods? I'm guessing it does, and a recent crash in one of my unit tests seems to confirm it. Apple's Advanced Memory Management Programming Guide doesn't say anything whether there's a difference between class and instance methods.
Update
What I mean that it also applies to class methods is really the "inverse". For instance, NSDecimalNumber has a class method called +decimalNumberWithDecimal:. It seems to return an auto released object (if I release it explicitly, a crash occurs shortly after that). In hindsight, the answer to my question is obvious, as Apple's guide refers to new and alloc as ownership-giving methods, and they're all class methods. Sorry for taking up your valuable time. :)
Also alloc and release. init does not indicate ownership, you are likely mixing that up with alloc. You can memorise it easily with the mnemonic NARC.
If you are naming any class methods init, copy or retain, you should stop that. Those are methods that only make sense in the context of instances. alloc and new are class methods and should only be used in that context. Don't name instance methods alloc or new.
The reason why the guide doesn't say that it applies to both instance methods and class methods is that the methods in question are clearly a mixture of both, so it's obviously the case.
Yes this applies to class methods since alloc and new are class methods which return ownership to the caller. The prefix of copy or mutableCopy should be used for instance methods returning ownership.
Edit For The Update:
You are correct a method like +decimalNumberWithDecimal: is expected to return an autoreleased object, therefore there is no reason to release it. If however they decided to name the method +newNumberWithDecimal: then you would have ownership of the returned object and need to release it. Clang static analyzer will actually complain if you prefix a method with new and return an autoreleased object.
Actually, this is almost correct. alloc, new, and copy give you ownership of the returned object. These are class methods. Other class methods should return an autoreleased object. Instance methods should also return an autoreleased object.
init does not effect ownership and should be use in conjunction with alloc as follows.
[[SomeCoolClass alloc] init]
new is usually the same thing as the above and is sometimes described as "almost deprecated" because it is a throwback to the NeXT days when the allocation and initialization were done in the same step and could not be plot apart as we do today with alloc and init.
Release does not effect ownership, but should only be used on object you already own. Otherwise a crash is likely to occur.
Retain also does not affect ownership, but should only be used on an object you already own. Otherwise the object may not be deallocated when it should be. The result could be a crash, but it can also be very very strange behavior that is difficult to troubleshoot because messages may be sent to the original object that was supposed to have been deallocated instead of a new object pointed to at the same address.

What is preferable in objective-c: id or explicit type?

What is better and why ?
What is better in such situations as the class init method and usual variables in a code ?
What is better and why ?
Explicit typing information is always better unless you just can't use it for some reason (see below).
It allows the compiler to much more stringently validate the code and will catch many errors at compile time that would otherwise cause your app to crash at runtime.
A long, long, time ago, everything in the APIs used id. This proved to be a complete pain in the butt; fragile and led to many crashes that would have been caught with specific types.
So, it was changed. (This was ~1994).
What is better in such situations as
the class init method and usual
variables in a code ?
For init, you have no choice but to use the generic (id) return type. Objective-C does not support either co-variant or contra-variant declarations, nor is there a mechanism for generalizing the declaration of init while also providing support for specific type checking.
Same goes for retain, objectAtIndex:, addObject: and many other methods that take or return one of many kinds of objects (or take 'em as arguments).
And, no, there is absolutely no performance difference whatsoever between id and, say, NSView*.
can you give an example when explicit
typing will cause a problem please?
If you wrote:
- (MyClass *) init;
And in a subclass:
- (MySubclass *) init;
You'd get compiler warnings out the wazoo most likely or you'd have to typecast out the wazoo.
On recent versions of clang (in Lion) you should actually not return id, and instead return instancetype. This is a keyword that is used in return types to specify that the type it returns is an instance of the class receiving the message. It is now the preferred return type for init methods on OS X Lion.
Explicit typing provides build-time protection, informing you of likely problems if you do things such as casting or performing operations on something that probably won't work.
Explicit typing also helps prevent non-obvious transfer of mistyped objects, something traveling through a path in your code you hadn't considered that turns out to be of an unexpected type. This kind of bug often doesn't become clear until the program has been tested a lot, more commonly after its release.
It's also helpful for future programmers (including your future self) trying to work with your code, making to more likely that they'll be able to tell at glance what an object is supposed to be. It makes code more "self-documenting" as a result.
Some things cannot have a meaningful type because no type actually applies. Other times you need to use id because you need to be able to accept any type of object. Cocoa Touch uses it, for example, when referring to the sender of a message because anything could have sent it; specifying an explicit type simply wouldn't work.
The vast majority of the time, though, an explicit type is to your advantage.
Use a type as specific as you can but not more so. Consider how you are using any particular variable, argument, or return type and set its type appropriately.
For example a UITableView's dataSource property is declared as id<UITableViewDataSource> because the table view only cares that its data source is some object which conforms to the UITableViewDataSource protocol. This allows the data source to be flexible enough for use with any specific class which implements the protocol but still allows the compiler to warn you if you attempt to assign an object which does not implement that protocol as the data source.
If you are too specific then your code becomes inflexible, accepting only specific implementations which are not strictly necessary (ie demanding a NSMutableString when you could really work with any NSString).
If you are too vague (typing everything as id for example) then you lose the ability to identify when you are sending unrecognized selectors to a particular instance and the compiler cannot identify any number of invalid statements.
For init methods follow the advice in The Objective-C Programming Language
The return type of an initializer method should be id.
The reason for this is that id gives an indication that the class is purposefully not considered—that the class is unspecified and subject to change, depending on context of invocation. For example, NSString provides a method initWithFormat:. When sent to an instance of NSMutableString (a subclass of NSString), however, the message returns an instance of NSMutableString, not NSString. (See also, though, the singleton example given in “Combining Allocation and Initialization.”)
I don't think there is a performance difference between both.
You can let id return type for init because you can cast the result of your init.
For exemple :
Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init];
Both work but you'll have to cast foo2 variable like that (Toto *)foo in order to access property or methods of your instance without creating a compiler warning. Even if it works fine...
I think some developers let id because they just pass there variable trough instance and don't use it. That kind of use allow to not import the .h
Regards,
KL94

Objective C - preferred way to create and initialize an object

Is one of these two ways to create and initialize an object preferable?
MyClass oClass = [[MyClass alloc] init];
oClass.length = 5;
oClass.text = #"Hello";
or using a class method that contains about the same code but looks like this:
MyClass oClass = [MyClass myClassWithLength:(int) 5 andText:(NSString *) #"Hello"];
I hate it when I see things done more than one way and I have no idea if one is better than the other, or why!
Don't be a hater. :-)
By the way, I'm assuming you meant:
(Edit: removed unnecessary casts)
MyClass oClass = [[MyClass alloc] initWithLength:5 andText:#"Hello"];
The reason for multiple init... methods is to make it more convenient for developers to create properly initialized instances. So, for example, if you find that developers often need to create instances of MyClass with a length and text, you make their life easier by providing an API that allows them to do that in one step. And if you find that developers also frequently need to create instances of MyClass with just a text string, you might also provide an -initWithText: method.
And if the instances created this way are frequently used as temporary objects (i.e., not stored in instance variables or static variables), you might also add a class convenience method like +myClassWithText: that returns an autoreleased instance of MyClass initialized with the provided text string.
As to which one is better: it's always better to fully initialize an object when possible, so if the object needs both values to be properly initialized, use the method that allows you to provide both arguments. And if you don't need to store a reference to the instance you're creating, use the class convenience method so your code doesn't have to deal with memory management.
If the object is unusable without the length and text, then the second option might be better. If those fields are optional, then the first one is better.
However, I don't think there is absolute truth to this question.
If you have a class with many properties it's very unlikely to initialize them all in one single line of code. Both ways work fine for me.
If an initWithSomething: method is available and you want to provide initial values for those properties, I would always prefer it just because it's simpler. It also will always work even with immutable versions of a class.
But neither init method is inherently "better." Classes usually have one or two designated initializers and all the others just call those with default values — it doesn't necessarily leave the instance's properties untouched. The documentation for a class should indicate what its initializers do and which is the designated initializer for the class. For example, [[NSDate alloc] init] uses NSDate's designated initializer, initWithTimeIntervalSinceReferenceDate:, to create a date object representing the current date and time.
Incidentally, this also means that when you're subclassing a class, you only need to override its designated initializer. Since the others just call that, they get your new behavior for free.

I need a good analogy to make sense of Class methods vs. instance methods

Im getting fairly confused as the book im reading is delving into the NSNumber class and talks about all the different methods you can call on it. I have a couple questions:
1.) Do you not have to call a typical alloc or init on foundation classes?
2.)in what cases would you use, say, numberWithChar: as opposed to initWithChar (i think this is the part that is messing me up the most, not really sure im groking this concept on the level i need to be, if you folks could break it down for me I think it would really help me get over this humper-roo.
Thanks,
Nick
Class/Instance Analogies
Classes are like blueprints for a type house. Instances are like actual houses. So you can only have one blueprint for a single type of house, but you can have multiple actual houses of the same type. Also, you can have multiple blueprints, and each blueprint describes a different type of house.
Another analogy you can use is that classes are like cookie cutters, and instances are like cookies made from a cookie cutter.
How It Applies To Objective-C
There is one "class object" for every class in your code. To refer to the class object, you just use the class name. alloc is a class method that allocates a new instance like so:
MyWidget* w = [MyWidget alloc];
However, alloc doesn't initialize the class, so none of the member variables will be set up. init is an instance method that will initialize a newly allocated instance. So to allocate and initialize a new instance, you do this:
MyWidget* w = [[MyWidget alloc] init];
Which is equivalent to this:
MyWidget* w = [MyWidget alloc]; //alloc is being called on the class
w = [w init]; //init is being called on the instance
Another common type of class method is a factory method like numberWithChar:. This is basically what numberWithChar: does:
+(NSNumber*) numberWithChar:(char)c;
{
return [[[NSNumber alloc] initWithChar:c] autorelease];
}
The only real difference is that numberWithChar: returns an autoreleased object.
All objects must be allocated and initialized. That includes foundation classes.
1) alloc and init need to be called virtually always. numberWithChar is a convenience method, which means it calls alloc, init, and autorelease for you and returns the autoreleased instance.
2) Since numberWithChar returns an autoreleased object, that means unless you retain it (or pass it to something like an NSArray which will retain it), it'll be destroyed shortly. initWithChar returns a retain-ed object, which means you have to release it when you're done with it.
I found when I was starting out that it was helpful to use init-alloc as a rule, instead of the convenience methods, because it made me pay close attention to my memory management.
The difference between class and instance methods is addressed from a number of angles in the answers to this question What is the difference between class and instance methods?
EDIT:
To be honest, the analogy I use when I call a class method on, say NSString, is praying to the god of NSStrings to bestow upon me a magnificent new NSString. Notice that class methods are almost 100% used for creation. e.g. alloc is a class method, stringWithFormat is a class method, and so on.
Yes, it's ridiculous, I know.
Ok, first thing: In Objective-C, you don't call a method, you send a message to an object. The runtime looks up the methods and calls them.
It might help you to think of a class as a factory. In fact, years ago, we used to refer to class methods as factory methods.