Как использовать свойство "copy" в Objective-C?
Я прочитал много материалов в Интернете, которые объясняют, когда люди должны использовать "copy
" вместо "strong
".
"Атрибут копирования является альтернативой сильному. Вместо того, чтобы владеть существующим объектом, он создает копию того, что вы назначаете этому свойству, а затем берет на себя ответственность. Только объекты, соответствующие протоколу NSCopying
может использовать этот атрибут..."
И есть много примеров кодов, показывающих при использовании "copy", исходное значение остается неизменным.
Однако я новичок в Objective-C
. Я действительно хочу знать, как использовать вновь назначенное значение. Где находится "новый экземпляр (копия)" с "новым значением"? Нужны ли какие-либо дополнительные методы для изменения исходного значения, если я хочу?
Будет здорово, если кто-то может поделиться примером для этой части, а не тот, который доказывает, что исходное значение не изменяется, что есть везде.
Ответы
Ответ 1
То, что атрибут copy
делает за кулисами, так это создание сеттера следующим образом:
- (void)setMyCopiedProperty:(MyClass *)newValue {
_myCopiedProperty = [newValue copy];
}
это означает, что всякий раз, когда кто-то делает что-то вроде этого object.myCopiedProperty = someOtherValue;
, someOtherValue
отправляется сообщение о copy
котором говорится, что оно должно дублироваться. Затем получатель получает новый указатель (при условии, что copy
правильно реализована), к которому никто, кроме объекта-получателя, не имеет доступа.
Вы можете посмотреть на copy
как на эксклюзивную:
- клиенты, которые устанавливают свойство, не имеют доступа к фактическому установленному значению
- получатель не имеет доступа к исходному переданному значению.
Остерегайтесь предостережений, хотя:
- скопированный
NSArray
не копирует свои объекты, поэтому вы можете подумать, что @property(copy) NSArray<MyClass *> *myProperty
безопасен, однако, хотя сам массив защищен от изменения, объекты, @property(copy) NSArray<MyClass *> *myProperty
в массиве поделиться той же ссылкой. То же самое верно для любого класса коллекции (NSDictionary
, NSSet
и т.д.) - если свойство соответствует пользовательскому классу, вам нужно убедиться, что метод
copy
выполняет свою работу - т.е. создает новый объект. Это происходит для всех классов Cocoa/CocoaTouch, которые соответствуют NSCopying
, однако для других классов это может быть или не быть правдой, в зависимости от реализации (сам я еще не видел класс, который лежит о его методе copy
, однако вы никогда не знаете)
Ответ 2
Попробуйте следующее:
model.h
@interface Model: NSObject
@property (nonatomic,strong)NSString *firstName;
@property (nonatomic,copy) NSString *lastName;
@end
ViewController.m
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
Model *model = [[Model alloc]init];
NSMutableString *str = [[NSMutableString alloc]initWithString:@"test"];
model.firstName = str;
model.lastName = str;
NSLog(@"%@, %@", model.firstName, model.lastName);
[str appendString:@"string"];
NSLog(@"%@, %@ ", model.firstName, model.lastName);}
Ответ 3
Экземпляр класса представляет собой дискретную копию. Когда вы назначаете экземпляр класса как значение свойства с атрибутом copy
, создается клон этого экземпляра и этот клон становится значением свойства. Между оригиналом и его клоном нет никакой связи, поэтому свойство вообще не имеет доступа к исходному экземпляру. Изменение атрибута значения свойства изменяет клон.
Примечание:
Если вы реализуете setter для свойства copy
, вы несете ответственность за то, чтобы он действительно создавал копию. Как и во всех атрибутах для свойства, они имеют смысл только тогда, когда компилятор генерирует (синтезирует) установщик и/или получатель для вас.