Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

NSMutableArray "replace object at index" problem

NewiPhoneDeveloperNewiPhoneDeveloper Posts: 459
edited April 2009 in iOS SDK Development
Hello,

In my latest project I'm using an NSMutableArray, but when I try to replace an object the app crashes (TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION).
- (void)ThisFunctionReplacesAnObject {
    [nameOfMyArray replaceObjectAtIndex:0 with Object: @newObject.png];
}

The NSMutableArray is declared in the .h file and released in .m (dealloc method).

What am I doing wrong here?

Thanks in advance
Post edited by NewiPhoneDeveloper on
Websites:<br />
<a href="http://www.friendlydeveloper.com"; target="_blank">Friendlydeveloper</a> - Coding Blog<br />
<a href="http://www.codingsessions.com"; target="_blank">Codingsessions</a> - Live iOS Training<br />
<br />
iPhone Apps: <br />
<a hr

Replies

  • iDevGuyiDevGuy Posts: 7
    edited September 2008
    There are two documented exceptions thrown by replaceObjectAtIndex. One results from withObject being nil; in your case that is unlikely. The other is that the index exceeds the bounds of the array: are you sure there is at least one pre-existing object in the array?
  • myersn024myersn024 Posts: 315
    edited September 2008
    To go along with what iDevGuy said, are you sure that you've alloc'ed and init'ed the NSMutableArray?
  • NewiPhoneDeveloperNewiPhoneDeveloper Posts: 459
    edited September 2008
    Thanks for your answers...

    I created the NSMutableArray as follows:
    myNSMutableArray = [[NSMutableArray alloc] init with objects:@object1.png, @object2.png, "object3.png"];
    

    "myNSMutableArray is also declared in the .h file, like:
    NSMutableArray *myNSMutableArray;
    
    //below @interface
    
    @property (nonatomic, retain) NSMutableArray *myNSMutableArray;
    

    I guess I'm just doing a stupid mistake here...
    Websites:<br />
    <a href="http://www.friendlydeveloper.com"; target="_blank">Friendlydeveloper</a> - Coding Blog<br />
    <a href="http://www.codingsessions.com"; target="_blank">Codingsessions</a> - Live iOS Training<br />
    <br />
    iPhone Apps: <br />
    <a hr
  • ckchengckcheng Posts: 8
    edited September 2008
    I have this problem before in my code, and let me guess, you have created the array in your "init" or "initWith...." method, right?

    To properly create a property with code (that is, not a UI control from Interface Builder) in "init" method, *always* retain your property.

    In short,

    myNSMutableArray = [[NSMutableArray alloc] initWith....];

    should be

    myNSMutableArray = [[[NSMutableArray alloc] initWith....] retain];

    this way, even your "init" method ends, the retain count of "myNSMutableArray" will prevent the system to free/release your object.

    Alternatively, since you declare the property in (retain) way, you can use

    self.myNSMutableArray = [[NSMutableArray alloc] initWith...];

    Using accessor will do the retain for you.
  • NewiPhoneDeveloperNewiPhoneDeveloper Posts: 459
    edited September 2008
    Hi,

    I tried what you suggested and it really makes sense to me, but still "TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION".

    Here is what I did:
    //this is MainViewController.m (NSMutable array is already declared in .h)
    
    myNSMutableArray = [[[NSMutableArray alloc] initWithObjects:@object1.png, @object2.png, @object3.png]retain];
    
    - (void)ReplaceOneOfMyObjects {
        [myNSMutableArray replaceObjectAtIndex:0 withObject:@object4.png];
    }
    
    [self ReplaceOneOfMyObjects];
    
    
    Websites:<br />
    <a href="http://www.friendlydeveloper.com"; target="_blank">Friendlydeveloper</a> - Coding Blog<br />
    <a href="http://www.codingsessions.com"; target="_blank">Codingsessions</a> - Live iOS Training<br />
    <br />
    iPhone Apps: <br />
    <a hr
  • ckchengckcheng Posts: 8
    edited September 2008
    It sounds strange.

    Have you tried print the count and the content of the array in your ReplaceOneOfMyObjects method before doing the replaceObjectAtIndex:withObject: ?
    NSLog([NSString stringWithFormat:@my array count = %d, content = %@", [myMutableArray count], myMutableArray]);
    
  • cleverappscleverapps Posts: 11
    edited September 2008
    Hi,

    I tried what you suggested and it really makes sense to me, but still "TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION".

    Here is what I did:
    //this is MainViewController.m (NSMutable array is already declared in .h)
    
    myNSMutableArray = [[[NSMutableArray alloc] initWithObjects:@object1.png, @object2.png, @object3.png]retain];
    
    - (void)ReplaceOneOfMyObjects {
        [myNSMutableArray replaceObjectAtIndex:0 withObject:@object4.png];
    }
    
    [self ReplaceOneOfMyObjects];
    
    

    "nil" is missing:
    myNSMutableArray = [[NSMutableArray alloc] initWithObjects: @object1.png, @object2.png, @object3.png, nil];
    
  • NewiPhoneDeveloperNewiPhoneDeveloper Posts: 459
    edited September 2008
    Sorry, forgot nil in my post.

    Anyway, I will investigate now every step in my app and report back.

    Thanks for all your help!
    Websites:<br />
    <a href="http://www.friendlydeveloper.com"; target="_blank">Friendlydeveloper</a> - Coding Blog<br />
    <a href="http://www.codingsessions.com"; target="_blank">Codingsessions</a> - Live iOS Training<br />
    <br />
    iPhone Apps: <br />
    <a hr
  • danzaphdanzaph Posts: 91
    edited September 2008
    ckcheng wrote: »
    To properly create a property with code (that is, not a UI control from Interface Builder) in "init" method, *always* retain your property.

    myNSMutableArray = [[NSMutableArray alloc] initWith....];
    should be
    myNSMutableArray = [[[NSMutableArray alloc] initWith....] retain];

    This is totally incorrect, alloc automatically retains as do methods with new or copy in them. The connivence class methods return a retained and autoreleased item and need to be retained it need be.
  • danzaphdanzaph Posts: 91
    edited September 2008
    1) You need a @synthesize call in the implementation.
    @synthesize myNSMutableArray;
    
    2) use "self." to use the setter/getters produced by the parameters.
    	self.myNSMutableArray = [[NSMutableArray alloc] initWithObjects:@object1.png, @object2.png, @object3.png, nil];
    	[self.myNSMutableArray replaceObjectAtIndex:0 withObject: @newObject.png];
    
    Without the "self." you are changing the iVar directly.
  • PhoneyDeveloperPhoneyDeveloper Posts: 1,431
    edited September 2008
    When you see the TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION message there is more info in the Xcode Debugger Console. Open up the console window and look for the kind of exception. As mentioned upthread there are different kinds of exceptions. Looking at the kind of exception will help you to figure out the problem. You can also see the NSLog output in Console.app.

    Also, by the time the app is terminated due to the uncaught exception there is no useful backtrace. If you set a breakpoint on objc_exception_throw the debugger will break before the exception is thrown and you'll have a useful backtrace. I do this with a .gdbinit file. Create a file named .gdbinit and place it in your home directory. This is the contents of mine:

    fb -[NSException raise]
    fb -[_NSZombie release]
    fb szone_error
    fb objc_exception_throw

    It's also possible to set these kinds of breakpoints in the Xcode breakpoints window or in the debugger console.

    At any rate, the usual reason for an exception with replaceObjectAtIndex is out of range. Another reason is that your instance variable has already been released due to faulty memory management so you message a stale pointer.
  • roberthuttingerroberthuttinger Posts: 96
    edited October 2008
    what if you want to replace one instance IN the object?

    if object1 at index 0 has 2 keys: firstname lastname;

    how would I replace the lastname Without touching the firstname? can you get that granular with an array? or do you have to write the entire array every change? doesnt this create a lot of overhead?

    cheers.bo
  • removerremover Posts: 27
    edited April 2009
    ckcheng wrote: »
    I have this problem before in my code, and let me guess, you have created the array in your "init" or "initWith...." method, right?

    To properly create a property with code (that is, not a UI control from Interface Builder) in "init" method, *always* retain your property.

    In short,

    myNSMutableArray = [[NSMutableArray alloc] initWith....];

    should be

    myNSMutableArray = [[[NSMutableArray alloc] initWith....] retain];

    this way, even your "init" method ends, the retain count of "myNSMutableArray" will prevent the system to free/release your object.

    Alternatively, since you declare the property in (retain) way, you can use

    self.myNSMutableArray = [[NSMutableArray alloc] initWith...];

    Using accessor will do the retain for you.



    thank you for this post. I would've been there all day. retain, retain, retain!
Sign In or Register to comment.