NSString @property, используя копию вместо сохранения - PullRequest
16 голосов
/ 25 февраля 2009

Я просматривал пример приложения Apple EditableDetailView и заметил, что в одном из своих контроллеров они устанавливают экземпляр свойства NSString с помощью (nonatomic, copy). Когда можно использовать копию вместо сохранения? Могут ли они сделать уникальную копию, не влияя на существующие данные?

Ответы [ 3 ]

38 голосов
/ 25 февраля 2009

Да, это так, что он может сделать уникальную копию, не затрагивая существующие данные. Синтезированные сеттеры по сути выглядят так:

// For @synthesize(nonatomic, retain) foo:
- (void) setFoo(NSFoo *theFoo)
{
    [theFoo retain];  // retain new value
    [foo release];    // release old value, if any
    foo = theFoo;     // assign new value
}

// For @synthesize(nonatomic, copy) foo:
- (void) setFoo(NSFoo *theFoo)
{
    NSFoo* newFoo = [theFoo copy];  // make copy
    [foo release];  // release old value, if any
    foo = newFoo;   // assign new value
}

Обратите внимание, что порядок операций здесь важен - новое значение должно быть сохранено / скопировано до того, как старое значение будет выпущено, в случае самостоятельного присвоения. Если вы сначала отпустили, а затем присвоили это свойство себе, вы можете случайно удалить это значение. Также обратите внимание, что если старое значение nil, отправка сообщения release в порядке, так как отправка сообщения объекту nil явно разрешена и ничего не делает.

Выбор сохранения по сравнению с копированием просто определяет, будет ли свойство объекта иметь то же значение, что и то, к которому вы его устанавливаете. Рассмотрим следующий код:

// suppose the 'foo' property is declared 'retain' and the 'bar' property is
// declared 'copy'
NSFoo *foo = ...;
NSBar *bar = ...;
someObject.foo = foo;
someObject.bar = bar;
[foo changeInternalState];  // someObject.foo also changes, since it's the same object
[bar changeInternalState];  // someObject.bar does NOT change, since it's a copy
3 голосов
/ 25 февраля 2009

Помните, что есть NS Mutable String. Было бы очень плохо иметь возможность изменять содержимое строки, которой владеет какой-либо другой объект (скажем, путем удаления половины его символов), особенно если вы не понимаете, что воздействуете на другой объект. Поэтому для другого объекта было бы хорошо сделать свою собственную копию.

Вы можете сказать «ну, почему бы мне просто не скопировать строку перед тем, как назначить ее там?». Может быть, объекту нужна изменяемая строка, а ваша неизменна. Если вам сначала нужно скопировать строку, то вам нужно найти, какую строку она хочет, в своей документации или заголовке, а затем сделать правильный вид копии (каждый раз). Таким образом, вы просто говорите other.string = myString и он делает любую копию, какую захочет - вам не нужно об этом беспокоиться.

0 голосов
/ 02 января 2010

(Почему-то этот пост появляется над последующим вопросом, на который я пытаюсь ответить) Re:

Вы имели в виду, что я должен скопировать объект foo 'перед выпуском 'foo' ?? но в чем проблема, если я Рене "Фу" перед копированием фу '?? потому что они два разных возражать, я не могу понять, почему высвобождение одного аффекта другому !!!!

В большинстве случаев вы правы. Если они на самом деле два отдельных объекта, это не имеет значения. Проблема заключается в том, что вы назначаете один и тот же объект обратно в себя. Если бы вы сказали

[myObject setFoo: moof];
[myObject setFoo: moof];

Тогда во второй раз, когда вы это сделали, вы отпустите moof, прежде чем скопировать его. В последующий момент, возможно, что если счет сохранения moof достигнет нуля, moof будет удален, и вам нечем будет копировать на следующем шаге. Фу теперь будет ноль.

Это может произойти? Наверное, больше, чем вы думаете. Конечно, бывают случаи, когда пользователь может дважды нажать кнопку «обновить», например.

Надеюсь, это понятно и полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...