Wdrażanie NSCopying
Przeczytałem NSCopying
dokumenty, ale nadal nie jestem pewien, jak wdrożyć to, co jest wymagane.
Moja klasa 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
Klasa Vendor
posiada tablicę obiektów o nazwie Car
.
Mój Car
obiekt:
@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
Tak więc Vendor
przechowuje tablicę Car
obiektów. Car
przechowuje 2 tablice innych obiektów niestandardowych.
Zarówno Vendor
jak i Car
są init ze słownika. Dodam jedną z tych metod, mogą być istotne lub nie.
-(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;
}
Tak aby podsumuj straszny problem.
Muszę skopiować tablicę Vendor
obiektów. Uważam, że muszę zaimplementować protokół NSCopying
na Vendor
, co może oznaczać, że muszę zaimplementować go również na Car
, ponieważ Vendor
posiada tablicę Car
s. oznacza to, że muszę również zaimplementować go na klasach, które są utrzymywane w dwóch tablicach należących do obiektu Car
.
Byłbym naprawdę wdzięczny, gdybym mógł uzyskać wskazówki dotyczące implementacji NSCopying
protokołu na Vendor
, nie mogę znaleźć żadnych tutoriali na ten temat gdziekolwiek.
3 answers
Aby zaimplementować NSCopying, obiekt musi odpowiedzieć na selektor -copyWithZone:
. Oto jak deklarujesz, że się do niego dostosowujesz:
@interface MyObject : NSObject <NSCopying> {
Następnie w implementacji obiektu (Pliku .m
):
- (id)copyWithZone:(NSZone *)zone
{
// Copying code here.
}
Co powinien zrobić twój kod? Najpierw Utwórz nową instancję obiektu-możesz wywołać [[[self class] alloc] init]
, aby uzyskać zainicjalizowany objct bieżącej klasy, która działa dobrze przy podklasowaniu. Następnie, dla zmiennych instancji, które są podklasą NSObject
, która obsługuje kopiowanie, można może wywołać [thatObject copyWithZone:zone]
dla nowego obiektu. Dla prymitywnych typów (int
, char
, BOOL
i przyjaciele) wystarczy ustawić zmienne na równe. Więc, dla Twojego sprzedawcy obejct, wyglądałoby to tak:
- (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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-27 19:35:17
Ta odpowiedź jest podobna do zaakceptowanej, ale używa allocWithZone:
i jest aktualizowana dla ARC. NSZone to podstawowa klasa alokacji pamięci. Chociaż ignorowanie NSZone
może działać w większości przypadków, nadal jest nieprawidłowe.
Aby poprawnie zaimplementować NSCopying
należy zaimplementować metodę protokołu, która przydziela nową kopię obiektu, z właściwościami odpowiadającymi wartościom oryginału.
W deklaracji interfejsu w nagłówku określ, że twoja klasa implementuje NSCopying
protokół:
@interface Car : NSObject<NSCopying>
{
...
}
W .implementacja m dodaje metodę -(id)copyWithZone
, która wygląda mniej więcej tak:
- (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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 00:42:43
Wersja Swift
Po Prostu zadzwoń object.copy()
, aby utworzyć kopię.
Nie używałem copy()
dla typów wartości, ponieważ są one kopiowane " automatycznie."Ale musiałem użyć copy()
dla class
typów.
Zignorowałem parametr NSZone
, ponieważ docs mówią, że jest przestarzały:
Ten parametr jest ignorowany. Strefy pamięci nie są już używane przez Objective-C.
Należy również pamiętać, że jest to uproszczona implementacja. Jeśli masz podklasy robi się trochę trudniej i powinieneś użyć dynamicznego typu: 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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-08 16:52:07