2013-03-26 12 views
9

To było bardzo często zadawane, ale to pytanie dotyczy przykładów użycia każdej z tych metod. Proszę użyć przykładów innych niż setter i nieskończonej pętli getteriOS, używając podkreślenia vs używania iVar bezpośrednio

przykład.

.h -
@property(nonatomic, strong)NSMutableArray* mutArray
.m -
@synthesize mutArray= _mutArray;

1) chciałbym:
_mutArray = [[NSMutableArray alloc] init];
LUB
self.mutArray=[[NSMutableArray alloc] init];
Dlaczego miałbym to zrobić każdy z nich, i jaka jest różnica ?!

2) Jeśli chcę dodać obiekt do niego ...
[_mutArray addObject:object];
LUB
[self.mutArray addobject:object];

i dlaczego ?!

Dziękuję bardzo!

Odpowiedz

12

Powinieneś zajmować się tylko twoimi ivars w init i dealloc lub gdy jest to absolutnie wymagane przez szczegóły implementacji (takie jak wewnątrz samego akcesora, lub gdy faktycznie potrzebujesz adresu pamięci). Inne niż w tych miejscach, należy zawsze używać akcesora, co oznacza [self foo] zamiast _foo.

self.foo to tylko cukier syntaktyczny dookoła rzeczywistego połączenia, czyli [self foo]. Ważne jest, aby zrozumieć, że self.foo jest standardową wiadomością wysyłania ObjC i oznacza dokładnie to samo, co [self foo]. Zgodnie z konwencją, powinieneś używać tylko składni punktowej w odniesieniu do właściwości.

Pre-ARC, bezpośrednie użycie ivarów było pierwszą przyczyną awarii w moim doświadczeniu.Prawdopodobieństwo, że popełnisz błąd podczas przypisywania bezpośrednio do ivar bez ARC, szybko zbliża się do 100% w stosunku do zakresu programu.

Od ARC wciąż twierdzę, że należy zawsze używać akcesorów (z wyjątkami podanymi powyżej), ale przyczyny są bardziej subtelne. Głównym powodem tego jest to, że akcesor może być dostosowany, albo w obecnej klasie, w podklasie, albo poprzez KVO (co dzieje się całkowicie poza twoim kodem). Jeśli uzyskasz bezpośredni dostęp do ivar, to obejdziesz to. Załóżmy na przykład, że właściwość jest tworzona leniwie (co jest dość powszechne). Jeśli użyjesz ivar, zanim zostanie on utworzony, dostaniesz subtelne błędy. Musisz więc pamiętać o tej właściwości, aby zawsze używać akcesora. Podobnie możesz zadzwonić pod numer setNeedsDisplay lub wysłać powiadomienie lub coś podobnego.

Jeśli masz prostą regułę, która mówi "zawsze będę używać akcesorów", łatwo będzie przejrzeć kod i wiedzieć, że jest właściwy. W kilku przypadkach musisz ominąć akcesorium, _ mówi "Hej, zwróć uwagę, robię coś dziwnego".

Jeśli masz regułę "użyję akcesorów dla właściwości, które jej potrzebują, ale nie dla tych, które tego nie robią", to prawie niemożliwe jest sprawdzenie kodu i sprawdzenie, czy jest ono poprawne. Czy poprzedni programista używał ivar, ponieważ był wymagany lub tylko dlatego, że tak się czuł? Czy możesz to zmienić, czy nie? Bardzo trudno o tym wiedzieć.

Więc nawet po ARC, konsekwentne używanie akcesorów jest dobrym programowaniem defensywnym i bardzo polecam.

+0

Cóż, to jest bardzo sprzeczne z odpowiedzią Ragnara! Co sądzisz o dodatkowej wartości dodanej, przechodząc przez setera? A także fakt, że inni ludzie mogą pracować z kodem i zmieniać setery/wywołania prowadzące do nieoczekiwanych wyników? – jgvb

+0

"Dodatkowe" zabezpieczenie nie jest "dodatkowym". Jest to wymagane utrzymanie, które należy zastosować, a przystawka jest właściwym miejscem do tego (dotyczy to tylko wstępnego ARC, ale niepoprawne zastosowanie, które zachowuje się poprawnie, jest główną przyczyną awarii, o których wspomniałem). Chcesz używać akcesorów dokładnie *, ponieważ * inne osoby mogą pracować nad kodem i nie ma sposobu, aby upewnić się, że wszyscy wiedzą i zawsze podążają za "kiedy zmieniasz to ivar, musisz również ..." Właściwy sposób na udokumentuj, że niestandardowe wymagania są realizowane przez akcesor. –

+0

Czasami może to prowadzić do zaskakujących wyników (np. Zbyt często przeliczania), ale te efekty uboczne prawie zawsze są znacznie łatwiejsze do debugowania niż fakt, że nie wiedziałeś, że musisz zadzwonić "setNeedsDisplay" po ustawieniu ivar. To prowadzi do rzeczy, które "robią coś innego, jak nie", które są wyjątkowo trudne do debugowania. Uruchomienie akcesora, gdy nie wiesz, że to się stanie, pojawia się na liście stosu. Nie udało się uruchomić akcesora, którego nie wiedziałeś, że musisz uruchomić .... to jest trudne do znalezienia. –

0

_mutArray to iVar, self.mutArray uzyskuje dostęp do właściwości za pomocą modułów pobierających i ustawiających, które są tworzone dla ciebie, gdy @syntetyzuje właściwość. Możesz nadpisać te moduły pobierające i ustawiające na odpowiednie niestandardowe elementy. W Twoim przykładzie własność jest silna, co dodaje zachętę do Twojej nieruchomości. So self.mutarray = [[NSMutableArray alloc] init]; by zrobić coś takiego (chyba, że ​​nad napisać setter tej posiadłości):

-(void)setMutarray:(NSMutableArray*)_mutArray{ 
    if(_mutArray != mutArray){ 
     [mutArray release]; 
     mutArray = nil; 
     mutArray = [_mutArray retain]; 
    } 
} 

Do dodawania obiektów do tablicy, co chcesz po prostu wejść do Ivar, a nie własność, chyba że robisz coś zwyczaj w getter . Na przykład jesteś przebojowa może wyglądać następująco:

-(NSMutableArray*)mutArray{ 
    if(!mutArray){ 
     self.mutArray = [[[NSMutableArray alloc] init] autorelease]; 
    } 
    return mutArray; 
} 

w ten sposób można zapewnić, że zawsze miałem prawdziwą tablicę dodawania obiektów. Jeśli tak jest, powinieneś użyć [self.mutArray addObject: object];

Tak więc, chyba że chcesz zrobić coś niestandardowego w geterze lub seterze, po prostu chcesz uzyskać dostęp do iVar.

+0

Dlaczego nie chcą przejść przez setter i getter chyba dostosować? – jgvb

+0

Nie chcesz przechodzić przez settera, ponieważ doda on zachowaj. Ponadto, jeśli inni ludzie pracują z kodem, mogą robić coś w geterze lub seterze, którego nie uwzględniasz. –

+0

Dziękuję bardzo. – jgvb

0

self Czy keyword jak thiskeyword w JAVA.

To dostęp do bieżącego obiektu, a także Jest to wskaźnik do obiektu.

for more info about self read this tutorial

_ObjeName nazywa iVar w Objective c

zmiennych instancji deklarowanych w realizacji są domyślnie ukryte (skutecznie prywatny), a widoczność nie może być zmieniony - @public, @protected and @private nie wytwarzają błędy kompilatora (z obecny Clang co najmniej), ale są ignorowane.

na przykład:

różnie

1)NSString *someString = _name;

2)NSString * someString = self.name;

Zakładam, że masz w pliku .m tej linii (i Nie mamy żadnych metod nadpisane na bezpośredni dostęp do _name)

@synthesize name = _name; 

To znaczy, że własność name (self.name) użyje zmiennej _name podczas próby do niego dostęp.W tym przypadku self.name jest równa _name


Ale jeśli mają właściwości dynamicznej nazwy, coś takiego:

-(NSString)name{ 
    return @"1234"; 
} 

to nie ma różnicy. self.name zawsze zwraca 1234, ale _nazwa może nie być równa tej wartości.

Przykład:

_name = @"555"; 
NSLog(_name); 
NSLog(self.name); 

Wynik:

2012-02-09 14:27:49.931 ExampleApp[803:207] 555 
2012-02-09 14:27:49.933 ExampleApp[803:207] 1234 

Above Example I Got From this Question.

+2

Powiedzenie, że "ja" jest jak "to", jest bardzo mylące dla nowych programistów. 'this' może być implikowane na Javie. 'self' nigdy nie jest implikowane w ObjC. Prowadzi to do dużego zamieszania, gdy dawni programiści Javy uważają, że '_name' i' self.name' oznaczają dokładnie to samo. Nigdy nie są identyczne, zawsze generują inny kod assemblera, mogą po prostu zwrócić ten sam wynik. –

+0

@RobNapier +1. Pochodzę z tła Java do ObjC i porównywałem także te "ja" i "ja", które, choć powiązane, są czymś zupełnie innym. – Petar

Powiązane problemy