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
は両方とも辞書からの初期化です。これらのメソッドの1つを追加します。関連する場合と関連しない場合があります。
-(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
オブジェクトの配列をコピーする必要があります。 NSCopying
にVendor
プロトコルを実装する必要があると思います。つまり、Car
にはVendor
の配列が保持されているため、Car
にも実装する必要があります。 [$ var] _s。つまり、Car
オブジェクトに属する2つの配列に保持されているクラスにも実装する必要があります。
NSCopying
にVendor
プロトコルを実装するためのガイダンスを得ることができれば、本当に感謝しています。これに関するチュートリアルはどこにもありません。
NSCopying を実装するには、オブジェクトが-copyWithZone:
セレクターに応答する必要があります。準拠すると宣言する方法は次のとおりです。
@interface MyObject : NSObject <NSCopying> {
次に、オブジェクトの実装(.m
ファイル)で:
- (id)copyWithZone:(NSZone *)zone
{
// Copying code here.
}
あなたのコードは何をすべきですか?最初に、オブジェクトの新しいインスタンスを作成します。[[[self class] alloc] init]
を呼び出して、現在のクラスの初期化されたオブジェクトを取得できます。これは、サブクラス化に適しています。次に、コピーをサポートするNSObject
のサブクラスであるインスタンス変数について、新しいオブジェクトに対して[thatObject copyWithZone:zone]
を呼び出すことができます。プリミティブ型(int
、char
、BOOL
およびその仲間)の場合、変数を等しくなるように設定するだけです。したがって、対象ベンダーの場合、次のようになります。
- (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;
}
この回答は受け入れられたものと似ていますが、_allocWithZone:
_を使用し、ARC用に更新されます。 NSZoneは、メモリを割り当てるための基本クラスです。 NSZone
を無視することはほとんどの場合うまくいくかもしれませんが、それはまだ間違っています。
NSCopying
を正しく実装するには、元の値と一致するプロパティを使用して、オブジェクトの新しいコピーを割り当てるプロトコルメソッドを実装する必要があります。
ヘッダーのインターフェイス宣言で、クラスがNSCopying
プロトコルを実装することを指定します。
_@interface Car : NSObject<NSCopying>
{
...
}
_
.m実装では、次のような-(id)copyWithZone
メソッドを追加します。
_- (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;
}
_
object.copy()
を呼び出してコピーを作成します。
値の型は「自動的に」コピーされるため、copy()
は使用しませんでした。しかし、class
型にはcopy()
を使用する必要がありました。
docs 推奨されていないと言うため、NSZone
パラメーターを無視しました。
このパラメーターは無視されます。メモリゾーンは、Objective-Cでは使用されなくなりました。
また、これは簡略化された実装であることに注意してください。 サブクラスがある場合、少し巧妙になりますので、動的型:type(of: self).init(transmissionType: transmissionType)
を使用する必要があります。
class Vendor {
let vendorId: String
var availableCars: [Car] = []
init(vendorId: String) {
self.vendorId = vendorId
}
}
extension Vendor: NSCopying {
func copy(with zone: NSZone? = nil) -> Any {
let copy = Vendor(vendorId: vendorId)
if let availableCarsCopy = availableCars.map({$0.copy()}) as? [Car] {
copy.availableCars = availableCarsCopy
}
return copy
}
}
class Car {
let transmissionType: String
var isAvailable: Bool = false
var fees: [Double] = []
init(transmissionType: String) {
self.transmissionType = transmissionType
}
}
extension Car: NSCopying {
func copy(with zone: NSZone? = nil) -> Any {
let copy = Car(transmissionType: transmissionType)
copy.isAvailable = isAvailable
copy.fees = fees
return copy
}
}