I've bought Xcode 4 in order to start developing iOS applications. I come from a background of C, C++.
I've entered the examples from here:
http://en.wikibooks.org/wiki/Objective-C_Programming/syntax
to an XCode project ( Command line tool->Foundation template, not that I know what it means, just what I read somewhere ).
I named the files: point.h, point.m, main.m
At first, I got 3 errors. I got rid of 2 of them by changing the class's name from "Point" to "MyClass"
but now i get the following warning:
Method '+new' not found (return type defaults to 'id')
About the line:
MyClass *point = [MyClass new]
I also get no output in the debugger output section.
Any ideas how to solve this?
Seems you've got some issues...
I would say you forgot to inherit from NSObject, so the method +new is not found.
#interface MyClass : NSObject
#end
Ok, let's start at the beginning. Read this.
Now, "+ new" is meaningful. It's telling you that your requesting to send a message to the CLASS "MyClass". This is very different from an instance of "MyClass". Class messages in other languages are referred to as "static methods" or "class methods". In ObjC, class methods are represented with a +, and instance methods are represented with a -.
The most common class method is alloc. In ObjC you send this message to the class to create a new instance and return it. Once you've allocated memory for the new instance, you can send the init message to it. From then on, you can retain or release it. I think you get the idea. Most messages are intended to be sent to the instance of a class, not the class itself.
So....
MyClass* c = [[MyClass alloc] init];
[c doStuff];
[c release];
First, we allocate new memory to hold an object of MyClass. Then we send it an init message to ensure that it's all setup properly. After that, we send a doStuff message to the initialized instance of MyClass stored in the c variable. Then we release the memory by sending a release message.
A note about retain/release.
When we allocated, the retain count goes from 0 to 1. When we released, the retain count goes from 1 to 0. This is akin to some "smart pointers" in other languages. Once the retain count reaches 0, the object is deallocated. So, when the release message is sent here, you should be able to set a breakpoint inside your MyClass dealloc block (an instance method). Just remember, when you specify init or dealloc blocks, always send the message to super as well so that you get proper cleanup.
edit:
Yes, I think you should inherit from NSObject as #macmade says. You get all kinds of really useful stuff from this base class like new, alloc, init, release, retain, autorelease, etc. The reason for this is because your instance will be living on the heap, not the stack. In a language like Java or C#, you would get this unified type system transparently. Since this is ObjC, you need to opt-in for it.
If you would rather manage your Point like a struct (have a look at the built in CGPoint), you can do that too, but in that case you would need to manage it very differently. It would be stack memory, not heap memory. You can get a good example of the difference by looking at the source to things like CGPoint or CGRect. Actually, all this stuff is very clearly documented in Apple's The Objective-C Programming Language.
Related
I recently learn objective-c from Programming Objective C, 4th edition.
I have question when reading to part:
myFraction = [Fraction alloc];
myFraction = [myFraction init];
When you send the alloc message to a class, you get back a new instance of that class. The alloc method is guaranteed to zero out all of an object’s instance variables. However, that doesn’t mean that the object has been properly initialized for use. You need to initialize an object after you allocate it.
Again, you are using a method here that you didn’t write yourself. The
init method initializes the instance of a class. Note that you are
sending the init message to myFraction. That is, you want to
initialize a specific Fraction object here, so you don’t send it to
the class—you send it to an instance of the class. Make sure you
understand this point before continuing.
So alloc and init is create each instance of class when I send message to class or instance of class?
I'm so confused about this. I searched on google but the result was found nothing. I need your help to make me clearly about it?
All of thing I know is alloc that allocate space in memory so it's actually not be created a new instance, just give me the address?
To begin with you just have some available memory with nothing in it.
When you call alloc, some of that free memory is reserved for your use for the instance that you are creating. Some basic setup work is done to configure the type of class that the instance is. Then you get a pointer back to the reserved memory location.
Technically, you could use this instance, but, it might not work properly in all cases as it hasn't been initialised. Some classes don't really need initialisation (like NSObject), some do. Generally you should never use the instance returned from alloc until you have called some init method.
After you call init, the instance is ready to use.
Sometimes the parameters that you pass to init mean that the initial instance that was reserved and created isn't the correct (class) type to use. In this case, it will be destroyed and a new one will be created for you. This is very common in class clusters where you create an NSArray instance, but then after calling init you might get back an NSCFArray. This is why you always need to use the instance returned from the init call, even though you already had the instance returned from alloc.
Usually you don't need to worry about this, but you do need to follow the rules.
So you always need to alloc and init an class.
Allocating means you give the class "Fraction" in this case a memory place. Afterwards you need to initialize the class "Fraction" so you can use it.
Fraction *class1 = [[Fraction alloc] init];
Fraction *class2 = [[Fraction alloc] init];
[class1 doSomethingWithClass1];
[class2 doSomethingWithClass2];
Later on you will learn about singletons. With that you can alloc/init a class one time, and always use that without alloc/init'ing it again.
I'm new to objective C and there's something odd that I don't understand.
How can I even call a NSString method on a NSDate object? For example:
NSString* ptr = [[NSString alloc] init];
[ptr uppercaseString];
NSDate* dPtr = [[NSDate alloc] init];
[dPtr uppercaseString];
id temp;
[temp uppercaseString];
Well, I do get that id can point to anything but how does it even know of the existence of the uppercaseString method without casting or something?
I'm have a C++ and Java background where I didn't notice anything like this before.
I'd love to get an explanation.
Unlike Java and C++, Objective-C has weak typing and late binding, which explains that you don't have to do a cast.
This is one of big dividing lines in object-oriented programming: Whether the language uses strong typing, so a variable can only hold references (or pointers) to objects of a given class and its subclasses, or if it can hold anything. If a variable can hold any object, the exact method implementation then has to be resolved at runtime when a message is received.
Objective-C got the philosophy of late binding from Smalltalk (see smalltalk), but is moving towards a more and more strictly typed language (formal protocols, use of the id type discouraged, etc.). The basics remain the same, however.
This is also one of the reasons, contrary to C++, Objective-C needs a runtime in order to run on your machine. Something has to take care of those method lookups.
Because the check for the existence of the method is not made right before the call but while trying to find the method. What actually happens (simplified a lot is)
[obj methodCall];
=> replaced => objc_send(obj, #"methodCall")
Inside the C function objc_send The call itself is resolved and made
If(obj.respondsTo(methodCall) Then obj.methodCall();
Objective-C methods are not the same as Java or C++ methods. They are messages, and they exist independently of any class or object. When you write (taken from CocoaDevCentral) in Photo.h:
#import <Cocoa/Cocoa.h>
#interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- caption;
- photographer;
#end
you are saying that the Photo class has a caption and a photographer object, and that it will respond to the messages caption and photographer. That was the old pre-properties way of writing code for those two items.
You will write code in Photo.m giving the implementation of the two messages, so that a Photo can respond to them. But nothing stops you from sending caption to any object. It's like the old Far Side cartoon about what we say to dogs and what they hear. Any errors occur at runtime.
So, what happens when you send a message to an object that it does not know how to respond to? If you have not done anything special,
The runtime system packages the message into a thing of type SEL.
It sends the doesNotRecognizeSelector: message to the object with that selector.
The object inherits from NSObject an implementation that raises a NSInvalidArgumentException.
However, there are a few opportunities before that to intervene by overriding a method:
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
This lets you install an implementation at runtime.
- (id)forwardingTargetForSelector:(SEL)aSelector
This lets you nominate another object to accept the message.
- (void)forwardInvocation:(NSInvocation *)anInvocation
This lets you handle the message any way you want.
Before Objective-C gained blocks, there were a number of libraries that used forwarding for functional programming. Suppose you have an NSArray of Accounts that all understand the balance message. Suppose then you want to collect the balances of all the accounts in another NSArray. Instead of looping, the library provided a category for NSArray with a collect message, and you would write:
NSArray *accounts = ...;
NSArray *balances = [[accounts collect] balance];
The result of [accounts collect] does not have an implementation for the balance message; how could it? collect is provided by the library. Instead, it has a forwardInvocation: implementation that sends the balance message to all the members of accounts, and creates a new NSArray from them. One might use blocks and enumerateObjectsUsingBlock: these days, but that was a quite succinct and powerful technique.
Others have provided the answer - late binding, the method is looked up on the object at runtime without concern for the type of the object - if it has an appropriate method it is called.
However your call above [dPtr uppercaseString] should produce an error from Xcode. While the compiler will perform a lot of checks and refuse to compiler some programs (such as the above) that is really all the type-checking you get and it can be easily by-passed (e.g. [(id)dPtr uppercaseString] will remove the error and let you code run - when it will promptly fault due to no such method on NSDate).
Essentially the types are comments, if you use them properly you code should be type-correct, but there is no requirement for type-correctness for your code to compile.
I wanted to know , How exactly does an Objective C object gets created. I have been reading different blog posts and apple docs but I could only find incomplete information here and there about ivar and objc_class structures ad various other runtime methods and structures.
But I still did not get, What happens when we call alloc on a Class and how are superclass data members added to the structure ?
If possible, can any one Explain this to me or point me to the source code of these methods that actually allocate memory ?
When alloc is called, it (as any other message send) first gets transformed (by the compiler) into one of the objc_msgSend* functions. This function will get the class structure pointer as its first argument, and #selector(alloc) as its second.
Then, objc_msgSend looks up the corresponding method implementation of +[class alloc], which is, in general, not overridden (custom initialization is conceptually done in -initWith...), so it will generally be +[NSObject alloc]. It is likely that alloc simply calls +[NSObject allocWithZone:]; that function's implementation might do the following steps:
1) It finds the class' istance size (probably via class_getInstanceSize())
2) It allocates memory, most likely using the class_createInstance() function. This function clears the allocated memory to zeroes (that's why, as the specs say, all your ivars are explicitly initialized to 0 on startup), then sets the newliy created object's isa pointer to the class structure itself.
3) The allocWithZone: methods returns the fresh object pointer to alloc
4) alloc returns the object pointer to the sender, most likely it will run into [Class initWith...:].
Hope this helps. Also, apart from the Obj-C runtime docs, don't forget to check the GNUstep NSObject implementations. That's a logic and possible way how the GNU people implemented it and how Apple might have implemented it.
Check out http://www.mikeash.com/pyblog/friday-qa-2009-03-13-intro-to-the-objective-c-runtime.html
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.
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.