Подтвердить что ты не робот

NSString @property, используя копию вместо сохранения

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

4b9b3361

Ответ 1

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

// 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 the same object
[bar changeInternalState];  // someObject.bar does NOT change, since it a copy

Ответ 2

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

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

Ответ 3

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

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

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

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

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

Возможно, это произойдет? Наверное, больше, чем вы думаете. Например, иногда пользователь может нажать кнопку "обновление" дважды, например.

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