2015-02-23 5 views
9

Ich führe diese Animation bei einer Benutzerinteraktion aus, und manchmal kann die Animation erneut ausgeführt werden, bevor die laufende Animation beendet ist. Was ich möchte, ist, die vorherige Animation abzubrechen und mit der neuen fortzufahren.UIView animateWithDuration Abschluss ist abgeschlossen = JA obwohl abgebrochen?

[UIView animateWithDuration:duration 
         delay:0 
        options:UIViewAnimationOptionBeginFromCurrentState 
       animations:^{ 
        self.bounds = bounds; 
       } 
       completion:^(BOOL finished) { 
        if (finished) { 
         // Do some cleanup after animating. 
        } 
       }]; 

Optisch scheint dies zu funktionieren, aber in meinem Abschluss Block mir gesagt wurde, dass es in beiden Fällen abgeschlossen, die der Bereinigungscode verursacht vorzeitig laufen. Der Completion-Block der ersten Animation wird also unmittelbar nach dem Start der zweiten Animation ausgeführt, wobei finished = YES. Ich erwartete, dass es einen fertigen Wert von NO hat und der zweite (sobald es fertig ist), YES zu haben.

Gibt es eine Möglichkeit zu wissen, ob die Animation abgeschlossen wurde oder ob sie durch eine andere abgebrochen wurde?

Nebenbei bemerkt: Ich habe versucht, die gleiche Animation mit CABasicAnimation tun und dann fertige ich = NO das erste Mal und YES das zweite Mal, so das Verhalten Ich scheint immer zu animateWithDuration spezifisch zu sein.

Hier ist ein GIF zeigt den obigen Code in Aktion mit einer Dauer von 10 und der Abschluss-Block aktualisiert die Bezeichnung. Wie Sie sehen können, finished ist YES die Animation jedes Mal mit dem animateWithDuration Aufruf neu gestartet wird:

Antwort

11

So untersuchte ich diese weiter und ich denke, das ist ein iOS 8 bestimmte Sache ist, darauf zurückzuführen, wie Animationen nun standardmäßig additiv sind, was bedeutet, dass die Animationen fortsetzen und addieren sich gegenseitig, anstatt abgebrochen zu werden.

In meiner Suche fand ich a WWDC session called "Building Interruptible and Responsive Interactions", die darüber spricht. In der Session behaupten sie, dass die Animationen alle gleichzeitig enden, aber das ist bei meinen Tests nicht der Fall (siehe das GIF in der Frage). Der Workaround, der in der Sitzung vorgeschlagen wird, besteht darin, einen Zähler für die Anzahl der Starts der Animation vs. abgeschlossen zu lassen und die Post-Animationsaktionen auszuführen, wenn der Zähler Null erreicht. Das ist ein bisschen hacky, aber funktioniert. Hier ist die Frage Code für diese angepasst:

// Add this property to your class. 
self.runningAnimations++; 
[UIView animateWithDuration:duration 
         delay:0 
        options:UIViewAnimationOptionBeginFromCurrentState 
       animations:^{ 
        self.bounds = bounds; 
       } 
       completion:^(BOOL finished) { 
        if (--self.runningAnimations == 0) { 
         // Do some cleanup after animating. 
        } 
       }]; 

Offensichtlich benötigen Sie einen separaten Zähler für jede Art von Animation, so dass es ein bisschen chaotisch am Ende zu bekommen, aber ich glaube nicht, dass es einen besseren Weg, es sei denn, Sie beginnen direkt mit CAAnimation.

+0

Danke, das half mir, meine Animationsfehler zu beheben, die immer auf iOS 9 beendet sind. – malhal

+0

Eigentlich ist ein besserer Weg, die Grenzen der Präsentationsschicht zu überprüfen, dann weißt du, ob es fertig ist oder nicht. – malhal

+0

Das habe ich auch gemacht (iOS 9.3, Swift)! Danke für die Hilfe. –

0

Welche Methode haben Sie die Animation abzubrechen versucht?

theView_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
[theView_ setBackgroundColor:[UIColor magentaColor]]; 
[self.view addSubview:theView_]; 

[UIView animateWithDuration:10 
       animations:^{ 
        theView_.frame = CGRectMake(200, 200, 50, 50); 
       } completion:^(BOOL finished) { 
        NSLog(@"done : %@", @(finished)); 
        if(finished) { 

        } 
        else { 

        } 
       }]; 

[self performSelector:@selector(cancelAnimation) withObject:nil afterDelay:2]; 

Die cancelAnimation Methode ist wie folgt:

- (void)cancelAnimation { 
    NSLog(@"cancel"); 
    [theView_.layer removeAllAnimations]; 

}

Die finished wird false zurück, wenn die Animation abgebrochen.

Log-Meldungen werden als erwartet:

2015-02-23 14:13:58.625 TestPrj[47338:6070317] cancel 
2015-02-23 14:13:58.626 TestPrj[47338:6070317] done : 0 
+1

Ja, aber der Aufruf von 'removeAllAnimations' bringt die Ansicht sofort in ihren endgültigen Zustand. Ich möchte die erste Animation mit einem zweiten Aufruf von 'animateWithDuration' abbrechen.Der zweite Aufruf löscht es deutlich (der "Completion" -Block wird direkt aufgerufen), aber der "Fertig" -Wert ist "YES" anstelle von "NO", so dass ich den Unterschied zwischen einer abgebrochenen Animation und einer tatsächlichen Animation nicht ausmachen kann fertig. – Blixt

+0

@Blixt Was Sie implementieren möchten, ist Anhalten/Fortsetzen der Animation mit Blockanimationsmethode. Haben Sie schon einmal http://stackoverflow.com/questions/15119839/uiview-animation-block-pause-both-the-animation-and-the-completion-code gesehen? – Ryan

+0

Das ist ordentlich, aber ich muss die Animation tatsächlich ersetzen, da die Animation von 'Grenzen' auf eine beliebige Position basierend auf der Eingabe des Benutzers geht. Gibt es eine Möglichkeit, den 'ToValue' der Animation zu ersetzen, anstatt ihn anzuhalten? – Blixt

Verwandte Themen