2013-06-06 8 views
8

referencyjny:IOS - performSelector: withObject: afterDelay: NIE DZIAŁA

https://stackoverflow.com/a/14741253/1749293

Podobnie jak w linku powyżej powiedziane, ale wydaje się, że nie wyjaśnia przyczyny.

W moim kodu dodaje zadziała:

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay:0.5]; 
}); 

ale kiedy skomentować coś takiego, (a ja naprawdę pewien, że go uruchomić w głównym wątku !!) Kod nie praca:

// dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay: 0.5]; 
// }); 

Czy ktoś może mi powiedzieć, dlaczego? I "self", będzie nerver zwolnienia/zwalniania, i zachować go, aż wniosek się kończy.

"nie działa", to znaczy, że (bez awarii) to nie wskoczyć "helloworld" metody:

-(void) helloWorld { 
    NSLog(@"hello world");  // I set a break point here for debug , it wouldn't pause forever 
} 

myślę jest Run Loop przyczyną tego problemu. Tak jak powiedział this link, ale potrzebuję więcej szczegółów lub dokładniej wyjaśnię.

+1

To dziwne, jeśli rzeczywiście jesteś w głównym wątku. Jakiś szczególny powód, dla którego nie używasz 'dispatch_after()'? –

+0

co to jest BROKER.actors.event? – manujmv

+0

W twoim pierwszym kodzie używasz 'self', podczas gdy w drugim używasz' BROKER.actors.event'. Czy na pewno odnoszą się do tego samego? – sunkehappy

Odpowiedz

21

Kiedy to się stało, dzwoniłem do performSelectora z wysyłki GCD. Tak więc ustawiał czasomierz w wątku roboczym GCD, który zniknął przed zwolnieniem timera. Gdy GCD usunął wątek roboczy, timer został utracony, więc selektor nigdy nie został wywołany.

+2

OP: "naprawdę pewny, że uruchomię go w głównym wątku". – Mar0ux

+1

+1 za dobre wyjaśnienie – onmyway133

1

EDIT Jak zauważył w komentarzach, performSelector: withObject: afterDelay: zachowuje również swój cel, więc ignorować moją odpowiedź. END EDIT

Przyjmuję, że używasz ARC. Twój blok zachowuje twój obiekt.

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay:aTimeUnit]; 
}); 

Dlatego selektor jest uruchamiany. Kiedy skomentujesz blok, nikt nie zachowa odniesienia do twojego obiektu, więc zostanie automatycznie zwolniony.

// dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay: aTimeUnit]; 
// }); 

Przez czas aTimeUnit upłynął, self prawdopodobnie został zwolniony, więc wywołanie selektor jest stracone. To Twój problem.

Należy unikać przechwytywania siebie wewnątrz bloku, ponieważ jeśli przechowujesz blok w ivar, możesz skończyć z cyklem zatrzymania, który powoduje, że obiekt nie zostanie zwolniony. Mówią o tym: How do I avoid capturing self in blocks when implementing an API?

+0

Wywołanie selektora do zwolnionego obiektu zazwyczaj kończy się awarią, prawda? –

+7

Jestem przekonany, że performSelector również zachowuje wszystko. –

+0

Myślałem też, jako w.sellers, że performSelector staje się właścicielem interesującego obiektu, zachowując go do momentu wykonania selektora, więc nie ma powodu, aby martwić się o samozaparcie w międzyczasie – meronix

Powiązane problemy