views:

85

answers:

4

I'm having some trouble with a NSMutableArray. I'm sure i'm doing something wrong with the allocation of the NSMutableArray but it's not obvious to me being an iPhone newbie. When i run the code below i can add the object MyObject to the array objects_ and set the name etc. The NSLog displays the correct data.

But when i try to access the objects_ member from the function printObject i get a SIGABRT. Looks like the memory has been deallocated or something?

Any help appreciated.


@interface MyObject : NSObject {
    NSString *name;
}

-(void) SetName:(NSString*) name_str;
-(NSString*) GetName;

@end

@interface ObjectListViewController : UITableViewController {
    NSMutableArray* objects_;
}

-(void) initTableData;

@end

@implementation ObjectListViewController

- (void)initTableData {
    objects_ = [[NSMutableArray alloc] initWithCapacity:10];
    MyObject *obj = [MyObject alloc];
    [obj SetName:@"Test"];
    [objects_ addObject:obj];

    MyObject* testObj = (MyObject*)[objects_ objectAtIndex:0];
    NSLog([testObj GetName]);
}

- (void)printObject {
    MyObject* testObj = (MyObject*)[objects_ objectAtIndex:0];
    NSLog([testObj GetName]);
}

A: 

MyObject *obj = [MyObject alloc];

should be: MyObject *obj = [[MyObject alloc] init];

Unikorn
A: 
    @interface ObjectListViewController : UITableViewController {
        NSMutableArray* objects_;
    }

   @property (nonatomic, retain) NSMutableArray *objects_;
   -(void) initTableData;
   -(void) printObject;

    @end

add the synthesize in the implementation

@implementation ObjectListViewController
@synthesize objects_;
Aaron Saunders
Good idea, but not the problem.
bbum
+1  A: 

We can eliminate the lack of an init call on MyObject as the cause of the crash as in this case it will be benign. Calling init on NSObject will just return self, so calling it in this case won't change the behaviour. So I don't think the first two answers here will make any difference:

An object isn’t ready to be used until it has been initialized. The init method defined in the NSObject class does no initialization; it simply returns self.

Chuck correctly points out that init is a fundamental step in object allocation and initialization and you should be calling it when you allocate MyObject.

I am not sure the third answer is correct either. I don't really see how adding synthesise on the objects_ array will make any difference. You haven't defined it as a property, and I don't really see why you would need to, given it is just data internal to the class.

The comment on the question Well, for starters, you never define printObject in the @interface. from eykanal doesn't really help you either, because you must be calling printObject internally, otherwise you wouldn't be hitting the crash.

Reading the through the code, I can't see an obvious error. The retain count on objects_ after initTableData finishes should be one, the retain count on the instance of MyObject should also be one. So I think there must be some other code that is releasing objects_ elsewhere?

I am assuming it is crashing on the objectAtIndex call? Is there any info in the console? What does the call stack look like?

Cannonade
yeah, I have to agree that init is not necessary. +1 for that
vodkhang
Whether `init` performs a useful function in this particular case, it's still required by the language. You're probably right that it's not the culprit here, but it's still wrong to say that "you don't need to call `init`" (and also, that's a comment, not an answer). So -1 for spreading inaccurate information. http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html#//apple_ref/doc/uid/TP30001163-CH22-SW1
Chuck
@Chuck I thought I had clarified that sentence with "despite it being good practice and you might want to do stuff in your MyObject init". I was eliminating the lack of init as the cause of the crash, which I think is a valid. Point taken however and I will try and clarify.
Cannonade
A: 

Here are some issues in your code:

  • You never initialise your MyObj object. Although it inherits directly from NSObject and NSObject is documented to do nothing except return self, you never know if other stuff happens behind the scenes, so put it in just to eliminate the posssibility.
  • Your methods don't follow the normal naming conventions. method names should begin with a lower case letter and "get" should only be used when passing back data by reference through the parameters as in e.g. NSData -getBytes:length:. Your getter and setter should be -name and -setName: respectively. This may seem like a minor nitpick, but it'll help you later on if you start to use KVO and KVC.
  • Never do NSLog(someStringVariable) always NSLog(@"%@", someStringVariable). As you have it now, if the object's name contains a percent formatting sequence e.g. %@, %d, %s etc, your program will crash on the NSLog. However, this is not the cause of your current problem - it would be crashing on the NSLog in -initTableData
  • you don't need to cast the result of -objectAtIndex:

Having said all that, I can't see anything that would cause the particular issue you have. It may be that the getter or setter for the name in MyObject is incorrect. Please post them.

JeremyP