2012-02-01 13 views
14

Ho un UIImageView inserito in UIScrollView, in base a questo UIImageView contiene una mappa molto grande e ha creato l'animazione su un percorso predefinito con direzione di navigazione puntata a "frecce".NSTimer non viene generato quando si verifica un evento di visualizzazione record

Tuttavia, ogni volta che si verificano arresti anomali, MainLoop si blocca e NSTimer non viene attivato e l'animazione viene interrotta.

Esistono proprietà esistenti che risolvono questo problema su UIScrollView, CAKeyFrameAnimation o NSTimer?

//viewDidLoad 
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(drawLines:) userInfo:nil repeats:YES]; 

- (void)drawLines:(NSTimer *)timer { 

    CALayer *arrow = [CALayer layer]; 
    arrow.bounds = CGRectMake(0, 0, 5, 5); 
    arrow.position = CGPointMake(line.x1, line.y1); 
    arrow.contents = (id)([UIImage imageNamed:@"arrow.png"].CGImage); 

    [self.contentView.layer addSublayer:arrow]; 

    CAKeyframeAnimation* animation = [CAKeyframeAnimation animation]; 
    animation.path = path; 
    animation.duration = 1.0; 
    animation.rotationMode = kCAAnimationRotateAuto; // object auto rotates to follow the path 
    animation.repeatCount = 1; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
    animation.fillMode = kCAFillModeForwards; 

    [arrow addAnimation:animation forKey:@"position"]; 
} 
+0

possibile duplicato di [UIScrollView mette in pausa NSTimer durante lo scorrimento] (http://stackoverflow.com/questions/7059366/uiscrollview-pauses-nstimer-while-scrolling) –

risposta

51

Applicazioni iOS eseguite su un NSRunLoop. Ogni NSRunLoop ha diverse modalità di esecuzione per diversi compiti. Ad esempio, il nstimer predefinito è pianificato per essere eseguito con NSDefaultRunMode su NSRunLoop. Ciò significa, tuttavia, che alcuni UIEvents, essendo uno scrollviewing, interrompono il timer e lo posizionano su una coda per essere eseguiti non appena l'evento si interrompe. Nel tuo caso, al fine di ottenere il timer non essere interrotto, è necessario pianificarlo per una modalità diversa, e cioè NSRunLoopCommonModes, in questo modo:

self.myTimer = [NSTimer scheduledTimerWithTimeInterval:280 
                   target:self 
                   selector:@selector(doStuff) 
                   userInfo:nil 
                   repeats:NO]; 
    [[NSRunLoop currentRunLoop] addTimer:self.myTimer forMode:NSRunLoopCommonModes]; 

Questa modalità consente il timer di non essere interrotto scorrendo . Puoi trovare ulteriori informazioni su queste informazioni qui: https://developer.apple.com/documentation/foundation/nsrunloop In basso vedrai le definizioni delle modalità tra cui puoi scegliere. Inoltre, la leggenda ce l'ha, puoi scrivere le tue modalità personalizzate, ma poche hanno mai vissuto per raccontare la storia impaurita.

+0

Bella spiegazione. – Robert

+2

Ehi, @GregPrice. Grazie per la spiegazione, anche 3 anni dopo. Tuttavia, il documento dice 'scheduledTimerWithTimeInterval: ...' crea un timer e * lo programma sul ciclo di esecuzione corrente nella modalità predefinita *. Quindi perché lo aggiungi due volte nel RunLoop predefinito, non solo una volta nella modalità 'NSRunLoopCommonModes'? – Martin

+0

'UIScrollView' esegue il ciclo di esecuzione in' UITrackingRunLoopMode', che è diverso da 'NSDefaultRunLoopMode'. Non è sufficiente programmare il timer per la modalità predefinita se si desidera che funzioni anche in altre modalità. –

Problemi correlati