实施 NSCopying
我已阅读 NSCopying 文档,但我仍然非常不确定如何实现所需的内容。
我的类 Vendor
:
@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
Vendor
类有一个名为 Car
的对象数组。
我的 Car
对象:
@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
因此,Vendor
保存一个 Car
对象数组。 Car
包含 2 个其他自定义对象的数组。
Vendor
和 Car
都是从字典中初始化的。我将添加其中一种方法,它们可能相关,也可能不相关。
-(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;
}
总结一下这个可怕的问题。
我需要复制 Vendor
对象的数组。我相信我需要在 Vendor
上实现 NSCopying
协议,这可能意味着我也需要在 Car
上实现它,因为 Vendor< /code> 保存一个
Car
数组。这意味着我还需要在属于 Car
对象的 2 个数组中保存的类上实现它。
如果我能获得一些关于在 Vendor
上实现 NSCopying
协议的指导,我将非常感激,我在任何地方都找不到任何关于此的教程。
I've read the NSCopying
docs but I am still very unsure about how to implement what is required.
My class Vendor
:
@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
holds an array of Car
objects. Car
holds 2 arrays of other custom objects.
Both Vendor
and Car
are init from a dictionary. I'll 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 to summarize the scary problem.
I need to copy an array of Vendor
objects. I believe I need to implement the NSCopying
protocol on Vendor
, which may mean I need to implement it also on Car
since Vendor
holds an array of Car
s. That means I also need to implement it on the classes that are held in the 2 arrays belonging to the Car
object.
I'd really appreciate it if I could get some guidance on implementing NSCopying
protocol on Vendor
, I can't find any tutorials on this anywhere.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实现 NSCopying,您的对象必须响应
-copyWithZone:
选择器。下面是如何声明您符合它:然后,在对象的实现中(您的
.m
文件):您的代码应该做什么?首先,创建对象的新实例 - 您可以调用 [[[self class] alloc] init] 来获取当前类的初始化对象,这对于子类化非常有用。然后,对于任何支持复制的
NSObject
子类的实例变量,您可以为新对象调用[thatObject copyWithZone:zone]
。对于原始类型(int
、char
、BOOL
等)只需将变量设置为相等即可。因此,对于您的对象供应商来说,它看起来像这样:To implement NSCopying, your object must respond to the
-copyWithZone:
selector. Here’s how you declare that you conform to it:Then, in your object’s implementation (your
.m
file):What should your code do? First, create a new instance of the object—you can call
[[[self class] alloc] init]
to get an initialized obejct of the current class, which works well for subclassing. Then, for any instance variables that are a subclass ofNSObject
that supports copying, you can call[thatObject copyWithZone:zone]
for the new object. For primitive types (int
,char
,BOOL
and friends) just set the variables to be equal. So, for your object Vendor, it’d look like this:此答案与已接受的答案类似,但使用
allocWithZone:
并针对 ARC 进行了更新。 NSZone 是分配内存的基础类。虽然忽略NSZone
可能适用于大多数情况,但它仍然是不正确的。要正确实现 NSCopying,您必须实现一个协议方法,该方法分配对象的新副本,其属性与原始值匹配。
在标头的接口声明中,指定您的类实现
NSCopying
协议:在 .m 实现中添加一个
-(id)copyWithZone
方法,如下所示:This answer is similar to the accepted, but uses
allocWithZone:
and is updated for ARC. NSZone is foundation class for allocating memory. While ignoringNSZone
might work for most cases, it is still incorrect.To correctly implement
NSCopying
you must implement a protocol method which allocates a new copy of the object, with properties that match the values of the original.In the interface declaration in the header, specify that your class implements the
NSCopying
protocol:In the .m implementation add a
-(id)copyWithZone
method which looks something like the following:Swift 版本
只需调用
object.copy()
即可创建副本。我没有使用
copy()
作为值类型,因为它们是“自动”复制的。但我必须对class
类型使用copy()
。我忽略了
NSZone
参数,因为 docs说它已被弃用:另请注意,这是一个简化的实现。 如果你有子类,那就有点麻烦了,你应该使用动态类型:
type(of: self).init(transmissionType: TransmissionType)
。Swift Version
Just call
object.copy()
to create the copy.I didn't use
copy()
for value types since those are copied "automatically." But I had to usecopy()
forclass
types.I ignored the
NSZone
parameter because docs say it is deprecated:Also, please note that this is a simplified implementation. If you have subclasses it gets a bit tricker and you should use dynamic type:
type(of: self).init(transmissionType: transmissionType)
.