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
zamiastretain
? - czy" kopiowana "nieruchomość jest w jakikolwiek sposób mniej wydajna niż taka" zachowywana"?
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
.)
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).
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 - adnotacjacopy
wskazuje, że naprawdę nie musisz się martwić o zmianę stanu obiektu w innym miejscu.
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ą.
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]
.
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.
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
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)
Zaimplementuj NSCopying zachowując oryginał zamiast tworzyć nowa kopia, gdy klasa i jej zawartość są immutable
Więc dla naszej niezmiennej wersji możemy po prostu zrobić to:
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
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ść.
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.
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