/ / NSTimer vyžadujúci, aby som ho pridal do runloopu - ios, Objective-C, Nstimer, nsrunloop

NSTimer vyžadujúci, aby som ho pridal do runloopu - ios, objective-c, nstimer, nsrunloop

Zaujímalo by ma, či niekto môže vysvetliť, prečo sa odosiela späť do hlavnej fronty a vytvára sa opakovanie NSTimer Musím to pridať do RUN LOOP, pretože to je príliš oheň? Aj pri použití performselectorOnMainThread Stále ho musím pridať do RUN LOOP, aby som ho spustil.

Nižšie uvádzam príklad mojej otázky:

#define queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define mainqueue dispatch_get_main_queue()

- (void)someMethodBeginCalled
{
dispatch_async(queue, ^{
int x = 0;
dispatch_async(mainqueue, ^(void){
if([_delegate respondsToSelector:@selector(complete:)])
[_delegate complete:nil];
});
});
}

- (void)compelete:(id)object
{
[self startTimer];

//[self performSelectorOnMainThread:@selector(startTimer) withObject:nil waitUntilDone:NO];
}

- (void)startTimer
{
NSTimer timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(callsomethingelse) userInfo:nil repeats:YES];

//NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];
}

EDIT: Verím, že som túto otázku formuloval veľmi zle. Chcel by som vedieť prečo [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes]; je potrebné v startTimer ak zavolám someMethodBeginCalled. Ak tento riadok nezaradím, časovač sa nespustí.

Ak zavolám startTimer z viewDidLoad napríklad môžem odstrániť NSRunLoop riadok a časovač sa spustí každých 60 sekúnd.

odpovede:

14 pre odpoveď č. 1

Namiesto toho môžete vždy použiť túto metódu:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(getBusLocation) userInfo:nil repeats:YES];

To vám ušetrí riadok, pretože sa automaticky pridá do cyklu run.


19 pre odpoveď č. 2

A tu je návod, ako pridať NSTimer na runloop:

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];

4 pre odpoveď č. 3

Pretože, ako docs hovoria:

Časovače pracujú v spojení s riadiacimi slučkami. Ak chcete efektívne používať časovač, mali by ste byť vedomí toho, ako fungujú riadiace slučky - pozri NSRunLoop a Sprievodca programovaním závitov. Pamätajte najmä na to, že slučky run sa zachovajú ich časovače, takže môžete časovač uvoľniť po jeho pridaní do a spustiť slučku.

Je to dizajnové rozhodnutie, ktoré Apple urobilo, keď napísali kód pre NSTimer (a som si istý, že na to mali dobrý dôvod), a že nemôžeme urobiť nič, aby sme ho obišli. Je to skutočne také zaťažujúce?


2 pre odpoveď № 4

Ako povedal @sosborn, NSTimerzáleží na NSRunLoops, a pretože fronty GCD vytvárajú vlákna, ktoré nemajú zabehnuté slučky, NSTimer nehrá sa dobre GCD.

Pozrite sa na túto ďalšiu otázku o StackOverflow: Je bezpečné naplánovať a zneplatniť NSTimery na sériovom fronte GCD?

Na vyriešenie tohto problému som implementoval MSWeakTimer: https://github.com/mindsnacks/MSWeakTimer (a nechal implementáciu skontrolovať inžinierom libdispatch na poslednom WWDC!)


0 pre odpoveď č. 5

Pridanie časovača do runloopu v mojom prípade nefungovalo. Musel som vytvoriť časovač na hlavnom vlákne. Toto vytváranie vlákna som robil v delegáte MultipeerConnectivity.

    dispatch_async(dispatch_get_main_queue(), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval  invocation: self.invocation repeats:YES];
});

0 pre odpoveď č. 6

Metóda časovača sa nebude volať, pretože fronty GCD vytvárajú vlákna, ktoré nemajú zabehnuté slučky

dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ { [NSTimer scheduledTimerWithTimeInterval: 1 opakovanie: blok ÁNO: ^ (NSTimer * _Nonnull časovač) { NSLog (@ "Metóda časovača z hlavného frontu GCD"); }];

});

Avšak pri odoslaní do hlavnej fronty sa zavolá metóda časovača, ktorá sa pridá do slučky chodu hlavných vlákien.

dispatch_async (dispatch_get_main_queue (), ^ { [NSTimer scheduledTimerWithTimeInterval: 1 opakovanie: blok ÁNO: ^ (NSTimer * _Nonnull časovač) { NSLog (@ "Metóda časovača z hlavného frontu GCD"); }];

});