Arseniy Spiridonov
Arseniy Spiridonov

Reputation: 337

How to do deep copying Objective-C

There is a class Patient with properties:

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) Symptoms *symptoms;
@property (assign, nonatomic) Status status;
@property (weak, nonatomic) id <PatientDelegate> delegate;

There is a class Symptoms with properties:

@property (assign, nonatomic) CGFloat temperature;
@property (assign, nonatomic) BOOL headache;
@property (assign, nonatomic) BOOL stomach_ache;

Both classes implement protocol NSCopying:

- (nonnull id)copyWithZone:(nullable NSZone *)zone {
    Patient *newPatient = [[[self class] allocWithZone:zone] init];
    [newPatient setName:self.name];
    [newPatient setSymptoms:self.symptoms];
    [newPatient setStatus:self.status];
    [newPatient setDelegate:self.delegate];
    return newPatient;
 }

- (nonnull id)copyWithZone:(nullable NSZone *)zone {
    Symptoms *newSymptoms = [[[self class] allocWithZone:zone] init];
    [newSymptoms setTemperature:self.temperature];
    [newSymptoms setHeadache:self.headache];
    [newSymptoms setStomach_ache:self.stomach_ache];
    return newSymptoms;
}

Also there is a class Doctor:

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSMutableArray *history;

- (void)makeNoteIn:(Patient *)patient card:(NSMutableArray *)history;
- (void)report;

When patient gets well, doctor calls method makeNoteIn:

- (void)makeNoteIn:(Patient *)patient card:(NSMutableArray *)history {
    Patient *newRecord = [patient copy];

    [history addObject:newRecord];
}

After the record is made, all property of the patient return to the original values. While we are in the method makeNoteIn and the current patient is proceeded, in history there is link to this object which has correct property values. As soon as we exit the method or start to proceed another patient, all the property values reset to the initial value.

I tried to realise copying, but something still wrong.

Describing of Patient and Symptoms classes

Situation when link on object was added to history, and object has right values

Situation when we went out from method makeNoteIn and objects has initial (wrong) values in history array

Upvotes: 2

Views: 77

Answers (1)

Sulthan
Sulthan

Reputation: 130082

When you want to deep-copy an object, you have to implement copy on all the substructures:

[newPatient setName:[self.name copy]];
[newPatient setSymptoms:[self.symptoms copy]];

Otherwise they will still reference the same object and changing one will affect all.

Note that you can do that automatically by declaring the properties as copy:

@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) Symptoms *symptoms;

It's common to use copy with NSString and NSArray to prevent assigning NSMutableString and NSMutableArray which could be changed externally by mistake. Make sure you implement NSCopying on Symptoms.

Upvotes: 3

Related Questions