PDA

View Full Version : Simple Question




tooom
Sep 7, 2010, 02:55 PM
I'm starting with objective c. I wrote the following stuff but I do not understand what I'm doing wrong

MyClass.h
#import <Cocoa/Cocoa.h>


@interface MyClass : NSObject {}

+(MyClass*) initMyClass;

@end

MyClass.m
#import "MyClass.h"

@implementation MyClass

+(MyClass*) initMyClass {
self = [super init];
return self;
}

@end

And Prog1.m
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSValue.h>
#import <stdio.h>
#import "MyClass.h"

int main (int argc, const char * argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

printf("1\n");
MyClass* myClass = [MyClass initMyClass];
printf("2\n");
[myClass autorelease];
printf("3\n");
MyClass* myClass2 = myClass;
printf("4\n");
[myClass2 retain];
printf("5\n");
[myClass release];
printf("6\n");


[pool release];
return 0;
}

There are some includes from XCode that are not necessary (i know). The program terminates and i do not understand why. I get the following error message on the console:
Program loaded.
run
[Switching to process 20067]
Running…
1
2010-09-07 21:10:49.667 Prog1[20067:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[MyClass<0x100001080> init]: cannot init a class object.'
*** Call stack at first throw:
(
0 CoreFoundation 0x00007fff83a27cc4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff86ef70f3 objc_exception_throw + 45
2 CoreFoundation 0x00007fff83a80f59 +[NSObject(NSObject) init] + 137
3 Prog1 0x0000000100000e67 +[MyClass initMyClass] + 57
4 Prog1 0x0000000100000d83 main + 103
5 Prog1 0x0000000100000d14 start + 52
6 ??? 0x0000000000000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
Program received signal: “SIGABRT”.
sharedlibrary apply-load-rules all


What's wrong here? :confused:



Catfish_Man
Sep 7, 2010, 03:09 PM
You're doing [MyClass initMyClass] instead of [[MyClass alloc] initMyClass]. You have to allocate space for an object before you can initialize it.

<edit>
Corollary: +initMyClass should be -initMyClass. An instance method, not a class method.
</edit>

chown33
Sep 7, 2010, 03:22 PM
I'm starting with objective c.
...
What's wrong here? :confused:

You're not telling us how you're starting with Objective-C.

Are you following an online tutorial?
Which one? Post its URL.

Are you reading a book?
Which one? Post its title and author.

Are you haphazardly trying code from various places on the internet?
Not a good idea. Almost any book or tutorial would be better.

jared_kipe
Sep 7, 2010, 04:31 PM
I think some of the confusion is on the usage of + vs - methods. I remember when I first started, I thought a lot of things should be + that really shouldn't be.

As stated before
+ methods can only be called on the class itself.
In Cocoa these are almost always convenience methods that return fresh objects or singleton instances.

For example, your class could be rewritten like this:

+ (MyClass *) newMyClass {
MyClass *newObject = [[MyClass alloc] init];
return [newObject autorelease];
}


Another example would be if you were writing a class to provide some math functionality..


+ (double) sin: (double) x {
// some sin() implementation
}

This method could be a class method because it doesn't require an instance to do its work. (It obviously could be a C function instead of a class method.)

Sydde
Sep 7, 2010, 07:48 PM
For example, your class could be rewritten like this:

+ (MyClass *) newMyClass {
MyClass *newObject = [[MyClass alloc] init];
return [newObject autorelease];
}


Hey there, oops: should you be using autorelease in a method that has "new" in the name? I mean, just for consistency sake.

tooom
Sep 8, 2010, 04:16 AM
Okay, thanks for the answers. I've modified my code in the following way
int main (int argc, const char * argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

printf("1\n");
MyClass* myClass = [[MyClass alloc] initMyClass];
printf("2\n");
[myClass autorelease];
printf("3\n");
MyClass* myClass2 = myClass;
printf("4\n");
[myClass2 retain];
printf("5\n");
[myClass release];
printf("6\n");


[pool release];
return 0;
}
Now, it runs. But I'm wondering if the object myClass has been added to the autoreleasepool?

Catfish_Man
Sep 8, 2010, 12:12 PM
Yes. Calling -autorelease on an object adds it to the topmost autorelease pool.

jared_kipe
Sep 21, 2010, 05:08 PM
Hey there, oops: should you be using autorelease in a method that has "new" in the name? I mean, just for consistency sake.

Generally yes. Since the method itself doesn't need to retain ownership. The caller should retain any object that it creates, and it is almost always assumed that the incoming object is autoreleased.