2010-08-31 9 views
6

Właśnie ściągnąłem Facebook iOS SDK i zauważyłem, że w przykładowym kodzie, które pochodzi z SDK, gdy tworzy instancję klasy Facebooku robi to tak:Efekt "myObj = [[[[MyClass alloc] init] autorelease] retain]; '?

_facebook = [[[[Facebook alloc] init] autorelease] retain]; 

gdzie _facebook jest zmienną członkiem obiektu wywołującego (tj. nie jest zmienną lokalną).

Czy ktoś może wyjaśnić dokładnie, co jest celem autoodlenia, a następnie zachować go?

+3

Hm, co do cholery ??? –

+2

Hmm, myślę, że lepiej odinstaluj aplikację Facebook. Oni wyraźnie nie rozumieją, co robią. – JeremyP

Odpowiedz

13

Skutecznie nie robi nic poza zużyciem niektórych cykli i pamięci.

Albo, dokładniej, w poprawnie napisanej aplikacji nic nie robi. W niepoprawnie napisanej aplikacji może maskować błąd przez wydłużenie czasu życia obiektu _facebook. Jednak nie jest to prawdziwa poprawka.

Znalazłem podobny wiersz kodu w http://github.com/facebook/facebook-ios-sdk/blob/master/sample/DemoApp/Classes/DemoAppViewController.m Jeśli to właśnie powołujesz się na to, tak, to nonsens.

+8

Alternatywna teoria mówi, że jest to symptom zapamiętywania bez zrozumienia. "Aby utworzyć obiekt, muszę napisać [[[ClassName alloc] init] autorelease]; trzymać się tego; Muszę to zachować. "Tylko autor oświadczenia wie na pewno. –

+0

Zrzucanie winy na ten plik przypisuje go do jednego dewelopera, może ktoś powinien wysłać e-mail z prośbą o wyjaśnienia na Github;) http://github.com/facebook/facebook-ios-sdk/blame/master/sample/DemoApp/Classes /DemoAppViewController.m – Shazron

+0

Tak, właśnie tak myślałem ... ale będąc w "oficjalnym" zestawie SDK na Facebooku myślałem, że być może pierwotny programista wiedział coś, czego nie zrobiłem, więc pomyślałem, że zapytam. Dzięki za wkład. – filipe

1

Chociaż jest możliwe, że znaleziony kod był po prostu niechlujny, ten wzór ma znaczenie.

"Alloc, autorelease, zachowują" zakłada, że ​​obiekt jest wymieniony w dwóch miejscach:

  • Jako wartości zwracanej na stosie wywołań (styl autorelease)
  • Według FB samego SDK (zwaną dalej " retain ')

Jest to ważne, jeżeli te dwa odnośniki mogą być niezależnie wydawane. Na przykład, jeśli SDK może zwolnić swój odnośnik PRZED ukończeniem stosu wywołań i opróżnieniu puli autorelease. Ok, jest to dość dopracowane; Co mam na myśli?

Rozważ te przypadki:

a) rzeczywisty kod

_facebook = [[[[Facebook alloc] init] autorelease] retain]; 

_facebook ma teraz licznik zatrzymywania z 2 i oczekuje 2 dzwonić do 'uwolnienia': 1 z kimkolwiek o nazwie " retain "i 1 w pewnym momencie w przyszłości, gdy NSAutoreleaseBeac spuszcza wodę.

B) proste „alternatywa” proponowane (NIE odpowiednik)

_facebook = [[Facebook alloc] init]; 

_facebook ma liczbę zatrzymywania z 1 i zostaną zniszczone podczas „uwolnienie” nazywa się (potencjalnie duży problem, jeśli pula autorelease nie została jeszcze opróżniona, a stos wywołań nadal używa obiektu)

Dlaczego to ma znaczenie? Wyobraźmy sobie taki kod:

@implementation (Thinger) 
+(id) make_new_thing 
{ 
    return my_copy_of_thing = [[[[Thing alloc] init] autorelease] retain]; 
} 
+(id) forget_about_thing 
{ 
    if (my_copy_of_thing != nil) { 
     [my_copy_of_thing release]; 
     my_copy_of_thing = nil; 
    } 
} 
@end 


void foo() { 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    id thing = [Thinger make_new_thing]; 
    [Thinger forget_about_thing]; 
    ... 
    [thing useThing]; // implementation B would break here ! 
    [pool drain]; 
} 
+0

Dla jasności, zdecydowanie * nie * konwencją jest kiedykolwiek pisać: [[[[[MyClass alloc] init] autorelease] retain] '. Raczej byłoby konwencją dla powyższej metody '+ make_new_thing' zwrócenie całkowicie nowej instancji autoreleased obiektu (tj.' Return [[[MyClass alloc] init] autorelease] ') i nie przechowywać odniesienia do starego. Byłoby bardzo źle zaprojektować metodę "tworzenia", która mogłaby potencjalnie zwolnić obiekty utworzone wcześniej przy każdym wywołaniu. – Sean

+0

Tak, przykład, który podałem, był całkiem sztuczny. Jednak jest "poprawny". Moja metoda make_new_thing wywołuje "release", ponieważ rezygnuje z odwołania "my_copy_of_thing". W ten sposób tylko "deallocates wcześniej utworzone obiekty", jeśli nie ma innych odniesień do tych obiektów. –

+0

Przepraszam, ale nie, to nie jest poprawne. Fakt, że należałoby napisać "... alloc] init] autorelease] retain]" jest znakiem, że sam projekt * jest niepoprawny. Istnieją lepsze sposoby projektowania tego rodzaju funkcji, które pozwoliłyby uniknąć zarówno zwariowanego zarządzania pamięcią, jak i dziwnych efektów ubocznych z metody create. – Sean

Powiązane problemy