2010-04-29 11 views
22

Próbowałem utworzyć właściwość, która jest tylko do odczytu. Chciałem zainicjować z wartością z klasy tworzącej instancję tej klasy, np.Inicjowanie właściwości readonly

@property (retain,readonly) NSString *firstName;

I próbował zainicjować to tak:

-(id)initWithName:(NSString *)n{ self.firstName = n; }

Kiedyś zrobiłam to, kompilator zgłosił błąd, że właściwość tylko do odczytu nie można przypisać. Jak mogę to zrobić?

Odpowiedz

13

Nie używać zsyntetyzowany setter:

firstName = [n retain]; //Or copy 

Powszechnie zaleca się ominąć ustawiające w dowolnych metod startowych i dealloc tak.

+0

Problem z powyższą implementacją polega na tym, że wartość nie została zachowana. Po dodaniu zatrzymania do nieruchomości, to przydział ustawi wartość na własność. A jeśli jakiś inny obiekt uzyska dostęp do tej właściwości, ta wartość będzie dostępna. Zmodyfikowałem również moje pytanie: – awsome

+0

Dlaczego to byłby problem? Użycie 'firstname = [n retain]' sprawi, że firstName będzie wskaźnikiem na 'n'. Tak więc, gdy jakiś inny obiekt uzyska dostęp do tej właściwości, wartość będzie tam. :) – Rengers

+0

Jeśli próbuję to zrobić w ten sposób, jeśli dostęp do tej właściwości, otrzymuję następujący wyjątek.Program otrzymał sygnał: "EXC_BAD_ACCESS". I ten błąd nie wynika z żadnej innej właściwości. Sprawdzałem to bardzo w debugerze. Ta właściwość pokazuje "poza zasięgiem". A jeśli przypiszę to, self.firstName = n;. wtedy wszystko działa dobrze. – awsome

38

Można bezpośrednio przypisać do zmiennej instancji (nie zapomnij dodać wartości retain lub copy, jeśli jest to potrzebne) lub ponownie określić właściwość w prywatnym rozszerzeniu klasy. Tak:

W swoim pliku .h:

@property (readonly, copy) NSString *firstName; 

W pliku .m:

@interface MyClass() 

// Redeclare property as readwrite 
@property (readwrite, copy) NSString *firstName; 

@end 


@implementation MyClass 

@synthesize firstName; 
... 

teraz można używać zsyntetyzowany setter w implementacji ale interfejs klasy nadal pokazuje własność jako tylko do odczytu. Zauważ, że inne klasy, które importują twój plik .h, wciąż mogą zadzwonić pod numer -[MyClass setFirstName:], ale nie będą wiedzieć, że istnieje i otrzymają ostrzeżenie kompilatora.

+0

To wygląda ładnie. Dzięki. – awsome

+0

Czy korzystasz z syntetyzowanego setera w porównaniu z podejściem sugerowanym przez @Renger? – Madbreaks

2

można bezpośrednio uzyskać dostęp do nieruchomości z:

_firstName = n;

Sposób seter że self.firstName = n oznacza nie będzie syntetyzowany ponieważ określony readonly w @property (retain,readonly) NSString *firstName;, stąd błąd kompilatora.

+0

nie ma _firstName ... –

+0

rozumiem, że _firstName będzie istnieć. Jest to ukryty ivar utworzony po zadeklarowaniu właściwości. Od Xcode 4.6 kompilator powinien automatycznie utworzyć to za Ciebie. – Bob9630

+0

To także moje zrozumienie @ Bob9630. Inne odpowiedzi na to pytanie nie przyniosły pożądanego rezultatu w moim przypadku, podczas gdy tak się stało. –