Właściwość NSString: Kopiuj czy zachowuj?

Powiedzmy, że mam klasę o nazwie SomeClass z string Nazwa właściwości:

@interface SomeClass : NSObject
{
    NSString* name;
}

@property (nonatomic, retain) NSString* name;

@end

Rozumiem, że nazwa może być przypisana NSMutableString w takim przypadku może to prowadzić do błędnego zachowania.

  • dla łańcuchów w ogóle, czy zawsze dobrym pomysłem jest użycie atrybutu copy zamiast retain?
  • czy" kopiowana "nieruchomość jest w jakikolwiek sposób mniej wydajna niż taka" zachowywana"?
Author: rptwsthi, 2008-12-23

10 answers

Dla atrybutów, których typ jest niezmienną klasą wartości zgodną z protokołem NSCopying, prawie zawsze należy podać copy w deklaracji @property. Określenie {[4] } jest czymś, czego prawie nigdy nie chcesz w takiej sytuacji.

Oto dlaczego chcesz to zrobić:

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

Bieżąca wartość właściwości Person.name będzie różna w zależności od tego, czy właściwość jest zadeklarowana retain Czy copy - będzie to @"Debajit" Jeśli właściwość jest zaznaczona retain, ale @"Chris" jeśli właściwość jest oznaczona copy.

Ponieważ w prawie wszystkich przypadkach chcesz zapobiec mutowaniu atrybutów obiektu za jego plecami, powinieneś zaznaczyć właściwości je reprezentujące copy. (A jeśli piszesz seter samodzielnie zamiast używać @synthesize, powinieneś pamiętać, aby w nim używać copy zamiast retain.)

 440
Author: Chris Hanson,
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
2012-04-12 06:21:05

Kopia powinna być użyta dla NSString. Jeśli jest zmienny, to zostaje skopiowany. Jeśli nie, to zostaje zatrzymana. Dokładnie taką semantykę, jaką chcesz w aplikacji (pozwól typowi robić to, co najlepsze).

 121
Author: Frank Krueger,
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
2008-12-23 02:11:39

Dla łańcuchów w ogóle, czy zawsze dobrym pomysłem jest używanie atrybutu copy zamiast keep?

Tak - na ogół Zawsze używaj atrybutu copy.

To dlatego, że Twój NSString property można przekazać instancja NSString lub instancja NSMutableString, w związku z tym nie możemy określić, czy przekazywana wartość jest obiektem niezmiennym czy zmiennym.

Czy" kopiowana "nieruchomość jest w jakikolwiek sposób mniej wydajna niż taka" zachowywana"?

  • Jeśli Twoja nieruchomość jest przekazywana instancja NSString, odpowiedź brzmi "No " - kopiowanie jest nie mniej efektywne niż zachowywanie.
    (Nie jest mniej wydajny, ponieważ NSString jest wystarczająco inteligentny, aby nie wykonać kopii.)

  • Jeśli Twoja nieruchomość zostanie przekazana NSMutableString instancja następnie odpowiedź brzmi "Yes " - kopiowanie jest mniej efektywne niż zachowywanie.
    (jest mniej wydajny, ponieważ musi nastąpić rzeczywista alokacja pamięci i kopia, ale jest to prawdopodobnie pożądana rzecz.)

  • Ogólnie rzecz biorąc, właściwość "kopiowana "może być mniej wydajna - jednak poprzez użycie protokołu NSCopying, możliwe jest zaimplementowanie klasy, która jest" tak samo wydajna " do kopiowania, jak do zachowania. instancje NSString są tego przykładem.

Ogólnie (nie tylko dla NSString), kiedy powinienem użyć "Kopiuj "zamiast"zachowaj"?

Powinieneś zawsze używać copy, gdy nie chcesz, aby wewnętrzny stan właściwości zmieniał się bez ostrzeżenia. Nawet dla obiektów niezmiennych-poprawnie napisane obiekty niezmienne będą efektywnie obsługiwać kopiowanie (patrz następna sekcja dotycząca niezmienności i NSCopying).

Mogą wystąpić powody do retain obiektów, ale wiąże się to z kosztami utrzymania-musisz zarządzać możliwością zmiany stanu wewnętrznego poza twoim kodem. Jak mówią - optymalizacja last.

Ale napisałem, że moja klasa jest niezmienna - nie mogę jej po prostu "zachować"?

No-use copy. Jeśli twoja klasa jest naprawdę niezmienna, najlepszą praktyką jest zaimplementowanie protokołu NSCopying, aby Twoja klasa sama wróciła, gdy copy jest używana. Jeśli to zrobisz:

  • inni użytkownicy twoja klasa uzyska korzyści z wydajności, gdy użyje copy.
  • adnotacja copy czyni Twój własny kod łatwiejszym do utrzymania - adnotacja copy wskazuje, że naprawdę nie musisz się martwić o zmianę stanu obiektu w innym miejscu.
 67
Author: TJez,
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
2012-05-23 07:14:45

Staram się przestrzegać tej prostej zasady:

  • Czy chcę zachować wartośćobiektu w momencie przypisania go do mojej własności? Użyj skopiuj.

  • Czy chcę trzymać obiekt i nie obchodzi mnie, jakie są lub będą jego wewnętrzne wartości w przyszłości? Użyj strong (zachowaj).

Do zilustrowania: czy chcę trzymać imię "Lisa Miller" (copy) czy do I want to hold on the person Lisa Miller (strong)? Jej imię może później zmienić się na "Lisa Smith", ale nadal będzie tą samą osobą.

 39
Author: Johannes Fahrenkrug,
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
2013-12-03 15:20:17

W tym przykładzie kopiowanie i zachowywanie można wyjaśnić następująco:

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

Jeśli właściwość jest typu copy, to

Zostanie utworzona nowa kopia dla [Person name] string, który będzie zawierał zawartość someName string. Teraz każda operacja na someName string nie będzie miała wpływu na [Person name].

[Person name] i someName łańcuchy będą miały różne adresy pamięci.

Ale w przypadku zatrzymania,

Oba [Person name] będą miały ten sam adres pamięci co łańcuch nazw, tylko liczba zachowanych ciągów nazw zostanie zwiększona o 1.

Więc każda zmiana w łańcuchu nazw będzie odzwierciedlona w łańcuchu [Person name].

 14
Author: Divya Arora,
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
2012-09-20 09:46:33

Z pewnością umieszczenie 'copy' w deklaracji właściwości jest równoznaczne z używaniem środowiska Obiektowego, w którym obiekty na stercie są przekazywane przez odniesienie-jedną z korzyści, które tu otrzymujesz, jest to, że podczas zmiany obiektu Wszystkie odniesienia do tego obiektu widzą najnowsze zmiany. Wiele języków dostarcza " ref " lub podobne słowa kluczowe, aby typy wartości (np. struktury na stosie) mogły korzystać z tego samego zachowania. Osobiście korzystałbym z copy oszczędnie i gdybym czuł, że wartość nieruchomości powinien być chroniony przed zmianami wprowadzonymi do obiektu, z którego został przypisany, mogłem wywołać metodę kopiowania tego obiektu podczas przypisywania, np.:

p.name = [someName copy];

Oczywiście, podczas projektowania obiektu, który zawiera tę właściwość, tylko Ty będziesz wiedział, czy projekt korzysta ze wzoru, w którym zadania pobierają kopie - Cocoawithlove.com ma do powiedzenia:

"powinieneś używać copy accessor, gdy parametr setter może być zmienny , ale nie możesz mieć wewnętrznego stan nieruchomości zmieniającej się bez ostrzeżenia " - więc ocena, czy możesz znieść wartość do nieoczekiwanej zmiany, jest twoja. Wyobraź sobie ten scenariusz:

//person object has details of an individual you're assigning to a contact list.

Contact *contact = [[[Contact alloc] init] autorelease];
contact.name = person.name;

//person changes name
[[person name] setString:@"new name"];
//now both person.name and contact.name are in sync.

W tym przypadku, bez użycia copy, nasz obiekt kontakt pobiera nową wartość automatycznie; jeśli jednak jej użyjemy, musielibyśmy ręcznie upewnić się, że zmiany zostały wykryte i zsynchronizowane. W tym przypadku zachowanie semantyki może być pożądane; w innym Kopia może być bardziej odpowiednia.

 3
Author: Clarkeye,
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
2012-05-21 21:52:57
@interface TTItem : NSObject    
@property (nonatomic, copy) NSString *name;
@end

{
    TTItem *item = [[TTItem alloc] init];    
    NSString *test1 = [NSString stringWithFormat:@"%d / %@", 1, @"Go go go"];  
    item.name = test1;  
    NSLog(@"-item.name: point = %p, content = %@; test1 = %p", item.name, item.name, test1);  
    test1 = [NSString stringWithFormat:@"%d / %@", 2, @"Back back back"];  
    NSLog(@"+item.name: point = %p, content = %@, test1 = %p", item.name, item.name, test1);
}

Log:  
    -item.name: point = 0x9a805a0, content = 1 / Go go go; test1 = 0x9a805a0  
    +item.name: point = 0x9a805a0, content = 1 / Go go go, test1 = 0x9a84660
 1
Author: len,
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
2014-03-07 03:10:41

Powinieneś używać copy cały czas, aby zadeklarować właściwość NSString

@property (nonatomic, copy) NSString* name;

Powinieneś je przeczytać, aby uzyskać więcej informacji o tym, czy zwraca niezmienny łańcuch (w przypadku przekazania zmiennego łańcucha) czy zwraca zachowany łańcuch (w przypadku przekazania niezmiennego łańcucha)

Nscopying Protocol Reference

Zaimplementuj NSCopying zachowując oryginał zamiast tworzyć nowa kopia, gdy klasa i jej zawartość są immutable

Obiekty Wartości

Więc dla naszej niezmiennej wersji możemy po prostu zrobić to:

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}
 0
Author: onmyway133,
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
2014-05-29 18:33:07

Ponieważ nazwa jest (niezmienna) NSString, kopiowanie lub zachowywanie nie ma znaczenia, jeśli ustawisz inną NSString Na nazwę. Innymi słowy, kopiowanie zachowuje się tak jak zachowywanie, zwiększając liczbę referencji o jeden. Myślę, że jest to automatyczna optymalizacja dla klas niezmiennych, ponieważ są one niezmienne i nie muszą być klonowane. Ale kiedy NSMutalbeString mstr jest ustawiona na name, zawartość mstr zostanie skopiowana ze względu na poprawność.

 -1
Author: GBY,
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
2012-11-15 08:11:50

Jeśli łańcuch jest bardzo duży, kopiowanie wpłynie na wydajność i dwie kopie dużego ciągu będą zużywać więcej pamięci.

 -1
Author: jack,
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
2015-01-17 17:11:39