0

I have another question for you that I believe I already know WHY it isn't working, but I'm not sure how to fix it...

I have a database array object using MutableNSArray. Let's call it "Database". This is an array of objects of type DatabaseRecord. I also have another DatabaseRecord object called CurrentRecord which is the active object I manipulate from the user interface. When I add a new entry into the database, I call:

[Database addObject: CurrentRecord];

When I'm done making changes, I replace the added record in the database with:

[Database replaceObjectAtIndex: <index> withObject: CurrentRecord];    

What I just realizes was that CurrentRecord is a pointer defined as:

DatabaseRecord *CurrentRecord;

I believe that what is happening is that each and every new entry in the database sets itself to the values of CurrentRecord. Likewise, when I change CurrentRecord, all of objects in the NSArray modify themselves accordingly, so I'm left with a database of, say, 100 records that are all identical.

What I want to do is essentially COPY the values of CurrentRecord into the appropriate object in the MutableNSArray.

I'm sure there's an easy fix to this, such as not passing a pointer, but I'm not quite sure how to proceed. I hope I'm being clear in my question...

1
  • The important point is how and when you initialize CurrentRecord. If you assign a new object to it whenever you want to work on a new entry, then there should be no problem...and also no reason to call the replaceObjectAtIndex: method. (As an aside, it would be easier to read your code if you used standard capitalization for variables, such as database and currentRecord so that they don't seem to be class names.) Commented Apr 28, 2012 at 22:02

2 Answers 2

3

When I'm done making changes, I replace the added record in the database

If you're changing records that are already in the array, there's no need to replace anything. Do this:

DatabaseRecord *currentRecord;

currentRecord = [database objectAtIndex:someIndex];
currentRecord.name = @"tom";
currentRecord.location = @"los angeles";

currentRecord = [database objectAtIndex:someOtherIndex];
currentRecord.name = @"harry";
currentRecord.location = @"new york";

Now you've just changed the contents of two of the records in the database -- no need to replace anything. The reason you can do this is that currentRecord is just a pointer to an object that already exists.

If you want to modify every record in the array, you can do:

for (currentRecord in database) {
    // make changes to currentRecord here
    // no need to replace the record in the array -- it's already there!
}

When you're adding new records to the database, on the other hand, you'll need to make sure that you create new objects each time. You can do that by copying an existing object, or by instantiating a new object each time yourself:

for (int i = 0; i < 10; i++) {
    currentRecord = [[DatabaseRecord alloc] init];
    [database addObject:currentRecord];
    // add [currentRecord release]; for non-ARC builds
}

or:

currentRecord = [[DatabaseRecord alloc] init];
for (int i = 0; i < 10; i++) {
    [database addObject:[currentRecord copy]];
    // make the previous line [database addObject: [[currentRecord copy] autorelease]]; for non-ARC builds
}

If you're not using ARC, you'll need to release the objects you create appropriately, as shown in the comments above.

I'm sure there's an easy fix to this, such as not passing a pointer

Nope. The only way to refer to an object in Objective-C is via pointer. The fix isn't difficult, though -- you just need to understand how pointers work a little better.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks much for the detailed explanation. After I posted I had some time to think about it while in the car and it occurred to me that I could probably just use a pointer to the "records" in the database, but wasn't entirely certain how to set that up. The example you posted above not only showed me how to do that, but I now have a better understanding of the way the pointers are working in my situation. Thanks!
1

So the problem is that everything in NSArray it's the same, right? You should use NSCopying protocol and

[Database addObject: [CurrentRecord copy]];

5 Comments

This may not work is CurrentRecord doesn't implement NSCoding, and a custom implementation may have to be written. This is the issue though.
@TomH: The relevant protocol is NSCopying (as SimpleMan alluded to), not NSCoding, but otherwise, yes: The CurrentRecord object must conform to NSCopying for you to be able to send it a copy message.
Thanks. I haven't tried it, but CurrentRecord is a subclass of NSObject I created.
So this is ok! You might have NSCopying protocol in your NSobject class! (ex: MySimpleClass : NSObject <NSCopying>)
@PeterHosey, oh oops, I messed up there. Yes, I apologise, for some reason my mind jumped to NSCoding not copying. You will probably need to write a custom implementation for it, it won't be inherited from NSObject's implementation, I don't think.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.