2012-03-29 21 views
27

W iOS5.0 z ARC, w moim kontrolerze rootview wywołuję metodę w obiekcie zarządzania bezpieczeństwem, który jest utrzymywany przez delegata aplikacji. W tej metodzie ustawiam timer poniżej:NSTimer nie uruchamia wybieraka

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self 
             selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

Jednak to nigdy nie uruchamia selektora, tj. updateModel: nigdy nie zostanie wywołany. Co może być nie tak? Czy istnieje inny skuteczniejszy sposób, w jaki mogę to zrobić bez użycia NStimer?

Odpowiedz

10

Wydajesz się być nieco pomieszany ze zmienną licznika czasu.

Inicjujesz nowy timer, ale w rzeczywistości go nie używasz. Czy chcesz użyć timera, który zainicjowałeś, czy też chcesz użyć ApplicationDelegate.timer?

Oto dwa możliwe rozwiązania.

Option One (zakładając, że masz instancję klasy zatytułowany ApplicationDelegate i że ma właściwość timer):

ApplicationDelegate.timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:ApplicationDelegate.timer forMode:NSRunLoopCommonModes]; 

Opcja druga:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
+0

zmartwiony ab z błędem w poście. Zmieniłem go tak, by odzwierciedlał sposób, w jaki to robię. Używam drugiego sposobu, o którym wspomniałeś ... Nadal nie działa. – inforeqd

+20

Drugi sposób jest nieprawidłowy. Próbuje dodać timer dwa razy. 'scheduledTimerWithTimeInterval: ...' dodał już zegar. Upewnij się, że uruchamiasz to w głównym wątku. –

+0

Czy jest jakiś sposób, aby dowiedzieć się, w którym wątku jest dodawany zegar? Myślę, że jest to główny wątek, który dodaję do ... – inforeqd

5

Linia ta ma kilka problemów:

[[NSRunLoop currentRunLoop] addTimer:ApplicationDelegate.timer forMode:NSRunLoopCommonModes]; 

Po pierwsze, nie powinno być w ogóle wymagane. -scheduledTimerWithTimeInterval:... dodaje już zegar do pętli. Nie musisz dodawać go ponownie.

Po drugie, lokalna zmienna timer nie jest związana z właściwością ApplicationDelegate.timer (która w tym momencie prawdopodobnie jest nil).

Jeśli rozmawiasz z aplikacją tak bardzo, że utworzyłeś coś o nazwie ApplicationDelegate (globalne? Makro?), Mówisz do niego zbyt wiele. Delegat aplikacji jest delegatem do aplikacji; pomaga w uruchamianiu i zatrzymywaniu aplikacji oraz reagowaniu na zdarzenia systemowe. Delegat aplikacji nie jest miejscem do przechowywania zmiennych globalnych. Czasomierz zdecydowanie nie jest rzeczą, którą można pobrać z innego obiektu.

+0

Przepraszam za błąd w poście. Zmieniłem go tak, by odzwierciedlał sposób, w jaki to robię ... Nadal nie działa. O twoim komentarzu do używania delegata aplikacji .. Mam model, który utworzę po przeanalizowaniu odpowiedzi serwisu WWW. Muszę zachować model dla wszystkich widoków w aplikacji. W związku z tym uważam, że model powinien być przechowywany przez delegata aplikacji w innym przypadku, nie jestem pewien, gdzie indziej mogę zachować go dla wszystkich poglądów do wykorzystania. – inforeqd

+1

Możesz przekazać model do kontrolerów widoku podczas konstruowania lub możesz umieścić obiekty modelu w singleton. Nie powinieneś ich powiesić na delegacie aplikacji. Powoduje to, że ponowne użycie kodu jest bardzo trudne i komplikuje delegata aplikacji (który ma swoją własną funkcję do wykonywania niezwiązanego z przechowywaniem danych). –

8

łapię ten sam problem i ogień czasomierza w głównym kolejce go rozwiązać:

[NSURLConnection sendAsynchronousRequest:request queue:_operationQueue 
    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ 
     [self loopUpUpdateStart]; 
}]; 

-(void)loopUpUpdateStart{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 

     _loopTimerForUpRevision = 
      NSTimer scheduledTimerWithTimeInterval: kNetworkLoopIntervalUpRev 
              target: self 
             selector: @selector(myCoolMethod) 
             userInfo: nil 
             repeats: YES]; 
     TRACE(@"Start Up updates"); 
    }); 
} 
105

Może być również problem gwintowania:

jeśli

[NSThread isMainThread] 

jest fałszywa wtedy zacząć minutnik taki jak ten:

dispatch_async(dispatch_get_main_queue(), ^{ 
     timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(tick:) userInfo:nil repeats:YES]; 
    }) 
+0

+1, dziękuję ... to załatwiło sprawę! – Joe

+1

Dzięki! Czy możesz wyjaśnić, czym jest problem z wątkami? – JohnH

+4

Timer działa poprawnie tylko w wątku głównym (UI). Jeśli spróbujesz uruchomić licznik czasu w innym wątku niż główny wątek, nie zostanie uruchomiony. – tmanthey