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
객체 배열을 복사해야 합니다. 에서 NSCopying
프로토콜 을 구현해야한다고 생각 Vendor
하는데, s 배열을 보유하고 Car
있기 때문에 구현해야 할 수도 있습니다 . 즉, 객체에 속하는 2 개의 배열에있는 클래스에서도이를 구현해야 합니다.Vendor
Car
Car
에서 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
친구)는 단지 동일하게 변수를 설정. 따라서 obejct Vendor의 경우 다음과 같이 표시됩니다.
- (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()
값 유형은 “자동으로”복사되므로 사용하지 않았습니다 . 그러나 나는 유형 에 사용해야 copy()
했습니다 class
.
문서에서 더 이상 사용되지 않는다고 말했기NSZone
때문에 매개 변수를 무시 했습니다.
이 매개 변수는 무시됩니다. Objective-C는 메모리 영역을 더 이상 사용하지 않습니다.
또한 이것은 단순화 된 구현입니다. 하위 클래스 가있는 경우 약간 까다로워지고 dynamic type :을 사용해야합니다 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
}
}