Implement NSCopying

I read the NSCopying , but I'm still very unsure how to implement what is required.

My Vendor Class:

 @interface Vendor : NSObject { NSString *vendorID; NSMutableArray *availableCars; BOOL atAirport; } @property (nonatomic, copy) NSString *vendorID; @property (nonatomic, retain) NSMutableArray *availableCars; @property (nonatomic, assign) BOOL atAirport; - (id)initFromVehVendorAvailsDictionary:(NSDictionary *)vehVendorAvails; @end 

The Vendor class has an array of objects called Car .

My Car Object:

 @interface Car : NSObject { BOOL isAvailable; NSString *transmissionType; NSMutableArray *vehicleCharges; NSMutableArray *fees; } @property (nonatomic, assign) BOOL isAvailable; @property (nonatomic, copy) NSString *transmissionType; @property (nonatomic, retain) NSMutableArray *vehicleCharges; @property (nonatomic, retain) NSMutableArray *fees; - (id) initFromVehicleDictionary:(NSDictionary *)vehicleDictionary; @end 

So, Vendor contains an array of Car objects. Car contains 2 arrays of other custom objects.

Both Vendor and Car are init from the dictionary. I will add one of these methods, they may or may not be relevant.

 -(id)initFromVehVendorAvailsDictionary:(NSDictionary *)vehVendorAvails { self.vendorCode = [[vehVendorAvails objectForKey:@"Vendor"] objectForKey:@"@Code"]; self.vendorName = [[vehVendorAvails objectForKey:@"Vendor"] objectForKey:@"@CompanyShortName"]; self.vendorDivision = [[vehVendorAvails objectForKey:@"Vendor"] objectForKey:@"@Division"]; self.locationCode = [[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"LocationDetails"] objectForKey:@"@Code"]; self.atAirport = [[[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"LocationDetails"] objectForKey:@"@AtAirport"] boolValue]; self.venLocationName = [[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"LocationDetails"] objectForKey:@"@Name"]; self.venAddress = [[[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"LocationDetails"] objectForKey:@"Address"] objectForKey:@"AddressLine"]; self.venCountryCode = [[[[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"LocationDetails"] objectForKey:@"Address"] objectForKey:@"CountryName"] objectForKey:@"@Code"]; self.venPhone = [[[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"LocationDetails"] objectForKey:@"Telephone"] objectForKey:@"@PhoneNumber"]; availableCars = [[NSMutableArray alloc] init]; NSMutableArray *cars = (NSMutableArray *)[vehVendorAvails objectForKey:@"VehAvails"]; for (int i = 0; i < [cars count]; i++) { Car *car = [[Car alloc] initFromVehicleDictionary:[cars objectAtIndex:i]]; [availableCars addObject:car]; [car release]; } self.venLogo = [[[vehVendorAvails objectForKey:@"Info"] objectForKey:@"TPA_Extensions"] objectForKey:@"VendorPictureURL"]; return self; } 

So, we summarize the terrible problem.

I need to copy an array of Vendor objects. I believe that I need to implement the NSCopying protocol on Vendor , which may mean that I need to implement it on Car as well, since Vendor contains an array of Car s. This means that I also need to implement it on classes that are stored in 2 arrays belonging to the Car object.

I would really appreciate it if I could get some recommendations on implementing the NSCopying protocol on Vendor , I can’t find any tutorials in this place.

+75
ios objective-c iphone nscopying
Nov 03 '10 at 16:28
source share
2 answers

To implement NSCopying , your object must respond to the -copyWithZone: selector. Here's how you state that you agree with him:

 @interface MyObject : NSObject <NSCopying> { 

Then in the implementation of your objects (your .m file):

 - (id)copyWithZone:(NSZone *)zone { // Copying code here. } 

What should your code do? First, create a new instance of the object - you can call [[[self class] alloc] init] to get the initialized obejct of the current class, which is well suited for the subclass. Then, for any instance variables that are a subclass of NSObject that supports copying, you can call [thatObject copyWithZone:zone] on the new object. For primitive types ( int , char , BOOL and friends) just set the variables equal. So, for your obejct Vendor, itd looks like this:

 - (id)copyWithZone:(NSZone *)zone { id copy = [[[self class] alloc] init]; if (copy) { // Copy NSObject subclasses [copy setVendorID:[[self.vendorID copyWithZone:zone] autorelease]]; [copy setAvailableCars:[[self.availableCars copyWithZone:zone] autorelease]]; // Set primitives [copy setAtAirport:self.atAirport]; } return copy; } 
+174
Nov 03 '10 at 16:42
source share

This answer is similar to accepted, but uses allocWithZone: and is updated for ARC. NSZone is the foundation class for memory allocation. Although ignoring NSZone can work in most cases, it is still incorrect.

To properly implement NSCopying , you must implement a protocol method that selects a new copy of an object with properties that match the values ​​of the original.

In the header declaration in the header, indicate that your class implements the NSCopying protocol:

 @interface Car : NSObject<NSCopying> { ... } 

In the .m implementation, add the -(id)copyWithZone , which looks something like this:

 - (id)copyWithZone:(NSZone*)zone { Car* carCopy = [[[self class] allocWithZone:zone] init]; if (carCopy) { carCopy.isAvailable = _isAvailable; carCopy.transmissionType = _transmissionType; ... // assign all other properties. } return carCopy; } 
+4
Jan 03 '17 at 17:19
source share



All Articles