user3720516
user3720516

Reputation:

Duplicating last object in array and then updating objective C

An array exists (named visits) which stores instances of Visit.

Scenario: A user click a button, enters a number, and that number is stored as a property on a newly created visit as a member of visits.

This is my code:

[visits addObject: [visits lastObject]];
Visit * lastVisit = [visits lastObject];
lastVisit.examDate = [NSLocale currentLocale];
lastVisit.edss_numeric = 5.5;

On inspection, I expected to have added a new visit to the end of my visits array (which it did) but the original last visit was then updated with the information I wanted to be set for the true last visit. In short, the last two visits are now identical and the originally copied visit changed (when it should not have).

What fundamentals of objective C am I not understanding and how can I fix this to achieve my desired results?

Upvotes: 1

Views: 65

Answers (2)

Ozgur Vatansever
Ozgur Vatansever

Reputation: 52173

[visits lastObject] returns a reference pointing to an object whose type is Visit. What you are doing is, adding that reference to the array again. Because of that, if you update the object through one of them, second reference will get affected since they both point to same object.

Does the Visit class implement NSCopying protocol? If it does, you can create a copy of the last object and add it to the array so you'll have two references pointing to two different objects:

@interface Visit: NSObject <NSCopying>

@property (nonatomic, strong) NSLocale *examDate;
@property (nonatomic, assign) CGFloat edss_numeric;

@end

--

@implementation Visit

- (id)copyWithZone:(NSZone *)zone {
  Visit *copy = [[self class] allocWithZone:zone];
  if (copy) {
    copy.examDate = [self.examDate copyWithZone:zone];
    copy.edss_numeric = self.edss_numeric;
  }
  return copy;
}

@end

Then, you can add the copy of the last object to the array as follows:

Visit *lastVisit = [visits.lastObject copy];
lastVisit.examDate = [NSLocale currentLocale];
lastVisit.edss_numeric = 5.5;

[visits addObject:lastVisit];

Upvotes: 3

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726799

When you do this

[visits addObject: [visits lastObject]];

you add a reference to the last Visit object to your NSArray again. Since it's only a reference, not a new object, any modifications to the "new last" will be reflected in the "old last" as well: it is the same object.

To fix this problem, insert a copy of last instead:

[visits addObject: [[Visit alloc] initWithOriginal:[visits lastObject]];

Add initWithOriginal: initializer to your Visit class, and copy the data as necessary into a new object.

Upvotes: 0

Related Questions