Допустим, у меня есть класс SomeClass
с string
именем свойства:
@interface SomeClass : NSObject
{
NSString* name;
}
@property (nonatomic, retain) NSString* name;
@end
Я понимаю, что имя может быть присвоено, и NSMutableString
в этом случае это может привести к ошибочному поведению.
- Для строк в целом всегда полезно использовать
copy
атрибут вместоretain
? - Является ли «скопированное» свойство каким-либо образом менее эффективным, чем такое «сохраняемое» свойство?
objective-c
cocoa
cocoa-touch
PlagueHammer
источник
источник
name
быть выпущенdealloc
или нет?Ответы:
Для атрибутов, тип которых является классом неизменяемых значений, который соответствует
NSCopying
протоколу, вы почти всегда должны указыватьcopy
в своем@property
объявлении. Вretain
такой ситуации вы почти никогда не хотите указывать.Вот почему вы хотите это сделать:
Текущее значение
Person.name
свойства будет отличаться в зависимости от того, объявлено ли свойствоretain
илиcopy
- будет,@"Debajit"
если свойство помеченоretain
, но@"Chris"
если свойство помеченоcopy
.Поскольку почти во всех случаях вы хотите предотвратить изменение атрибутов объекта за его спиной, вы должны пометить свойства, представляющие их
copy
. (И если вы пишете установщик самостоятельно, а не используете,@synthesize
вы должны помнить, что нужно использоватьcopy
вместоretain
него).источник
NSMutableString
, за исключением временного типа «строителя строк» (из которого я немедленно беру неизменную копию). Я бы предпочел, чтобы они были дискретными типами - но я позволю, чтобы тот факт, что копия является бесплатной, сохранит ее, если исходная строка не будет изменяемой, уменьшит большую часть моей озабоченности.Копия должна использоваться для NSString. Если он изменчив, он копируется. Если это не так, то это просто сохраняется. Именно семантика, которую вы хотите в приложении (пусть тип делает то, что лучше).
источник
NSString
свойство, объявленное какcopy
, всеretain
равно получит (если оно неизменное, конечно). Другой пример, который я могу придуматьNSNumber
.Да, вообще всегда используйте атрибут копирования.
Это связано с тем, что вашему свойству NSString можно передать экземпляр NSString или экземпляр NSMutableString , и поэтому мы не можем реально определить, является ли передаваемое значение неизменным или изменяемым объектом.
Если вашему свойству передается экземпляр NSString , ответ « Нет » - копирование не менее эффективно, чем сохранение.
(Это не менее эффективно, потому что NSString достаточно умен, чтобы фактически не выполнять копирование.)
Если вашему свойству передается экземпляр NSMutableString, тогда ответ « Да » - копирование менее эффективно, чем сохранение.
(Это менее эффективно, потому что фактическое выделение памяти и копирование должны произойти, но это, вероятно, желательно.)
Вообще говоря, «скопированное» свойство потенциально может быть менее эффективным - однако, используя
NSCopying
протокол, можно реализовать класс, который «столь же эффективен» для копирования, как и для сохранения. NSString экземпляры являются примером этого.Вы должны всегда использовать,
copy
когда вы не хотите, чтобы внутреннее состояние свойства изменялось без предупреждения. Даже для неизменяемых объектов - правильно написанные неизменяемые объекты будут эффективно обрабатывать копии (см. Следующий раздел об неизменяемости иNSCopying
).У
retain
объектов могут быть причины производительности , но это связано с накладными расходами на обслуживание - вы должны управлять возможностью изменения внутреннего состояния вне вашего кода. Как говорится - оптимизируй последний.Нет - использовать
copy
. Если ваш класс действительно неизменяемый, то лучше всего реализоватьNSCopying
протокол, чтобы он возвращал сам класс приcopy
использовании. Если вы делаете это:copy
.copy
Аннотаций делает свой собственный код более ремонтопригодны -copy
аннотацию указывает на то, что вы действительно не нужно беспокоиться об этом объекте меняющегося состояния в другом месте.источник
Я стараюсь следовать этому простому правилу:
Хочу ли я сохранить значение объекта в тот момент, когда я присваиваю его свойству? Используйте копию .
Хочу ли я удерживать объект, и мне все равно, каковы его внутренние значения в настоящее время или будут ли они в будущем? Используйте сильный (сохранить).
Чтобы проиллюстрировать: хочу ли я удержать имя «Лиза Миллер» ( копия ) или я хочу удержать человека, Лиза Миллер ( сильная )? Позже ее имя может измениться на «Лиза Смит», но она все равно останется тем же человеком.
источник
С помощью этого примера можно объяснить, как скопировать и сохранить, например:
если свойство имеет тип copy, то
новая
[Person name]
строка будет создана для строки, которая будет содержать содержимоеsomeName
строки. Теперь любая операция соsomeName
строкой не будет влиять на[Person name]
.[Person name]
иsomeName
строки будут иметь разные адреса памяти.Но в случае сохранения,
оба
[Person name]
будут иметь тот же адрес памяти, что и строка соменам, просто число сохраненных строк соменам будет увеличено на 1.Таким образом, любое изменение в строке somename будет отражено в
[Person name]
строке.источник
Безусловно, добавление «copy» к объявлению свойства противоречит использованию объектно-ориентированной среды, в которой объекты в куче передаются по ссылке - одно из преимуществ, которые вы получаете, заключается в том, что при изменении объекта все ссылки на этот объект увидеть последние изменения. Многие языки предоставляют «ref» или подобные ключевые слова, чтобы позволить типам значений (то есть структурам в стеке) получить выгоду от того же поведения. Лично я бы использовал копирование экономно, и если бы я чувствовал, что значение свойства должно быть защищено от изменений, внесенных в объект, которому он был назначен, я мог бы вызвать метод копирования этого объекта во время назначения, например:
Конечно, при разработке объекта, содержащего это свойство, только вы будете знать, выиграет ли дизайн от шаблона, в котором назначения получают копии - Cocoawithlove.com может сказать следующее:
«Вы должны использовать средство доступа к копии, когда параметр setter может быть изменяемым, но вы не можете изменить внутреннее состояние свойства без предупреждения », поэтому решение о том, можете ли вы выдержать неожиданное изменение значения, принадлежит вам. Представьте себе этот сценарий:
В этом случае, без использования копирования, наш контактный объект автоматически принимает новое значение; однако, если бы мы его использовали, нам бы пришлось вручную убедиться, что изменения были обнаружены и синхронизированы. В этом случае сохранение семантики может быть желательным; в другом случае копия может быть более подходящей.
источник
источник
Вы должны использовать copy все время, чтобы объявить свойство NSString
Вы должны прочитать их для получения дополнительной информации о том, возвращает ли она неизменяемую строку (в случае, если изменяемая строка была передана) или возвращает сохраненную строку (в случае, если неизменная строка была передана)
NSCopying Protocol Reference
Объекты значения
источник
Поскольку имя является (неизменяемым)
NSString
, копировать или сохранять не имеет значения, если вы установите другоеNSString
имя. Другими словами, копирование ведет себя как сохранение, увеличивая количество ссылок на единицу. Я думаю, что это автоматическая оптимизация для неизменяемых классов, поскольку они неизменяемы и не требуют клонирования. Но когдаNSMutalbeString
mstr
для имени установлено имя, содержимоеmstr
будет скопировано во имя правильности.источник
Если строка очень большая, то копирование повлияет на производительность, и две копии большой строки будут использовать больше памяти.
источник