2012-11-13 6 views
13

Ich brauche einen Fall zu behandeln, wo man etwas mit oder ohne Animation, statt zu tun:UIView Animationsblock: Wenn Dauer 0 ist, ist es das gleiche wie ohne Animation?

if (animation) 
{ 
    [UIView animateWithBlock:^(){...}]; 
} 
else 
{ 
    ... 
} 

ich tun möchte:

[UIView animateWithBlock:^(){...} duration:(animation ? duration : 0)] 

aber nicht sicher, ob es funktioniert, auch wenn es Gibt es einen Overhead für die Verwendung, anstatt die Ansicht direkt zu ändern? der Übergang effektiv durch sofortige

Dank

Antwort

7

Ja, da die Dauer Null ist.

+1

Und tut Hat es irgendeinen Overhead? dh. '[UIView animateWithBlock: ^() {self.view.frame = newFrame} mitDauer: 0]' vs 'self.view.frame = newFrame'? – hzxu

+0

Sie müssten den Rahmen zuerst einstellen, damit er sich wie jeder andere Frame verhält. - Ja, es wird einen Overhead haben. – PappaSmalls

+9

Ich habe dies mit iOS 7.1.1 5S getestet und der Unterschied ist enorm; das Setzen eines zufälligen Rahmens für eine Ansicht 10k mal dauerte 22,85 Sekunden mit^animateWithBlock:^und 0,05 Sekunden mit einem direkten Aufruf des Blocks. Wenn Sie jedoch nur wenige Animationsaufrufe für eine Benutzerinteraktion durchführen, ist der Unterschied nicht relevant. Bitte beachten Sie, dass Apple das Verhalten in Zukunft möglicherweise ändern und diesen Randfall optimieren kann. – mkko

27

Was ich in diesen Fällen mache, ist einen Block zu erstellen, der alle Animationen enthält, die ich machen möchte. Führen Sie dann eine UIView-Animation aus, indem Sie den Animationsblock als Parameter übergeben oder direkt diesen Block aufrufen, unabhängig davon, ob er animiert werden soll oder nicht. Etwas wie folgt aus:

void (^animationBlock)(); 
animationBlock=^{ 
     // Your animation code goes here 
}; 
if (animated) { 
    [UIView animateWithDuration:0.3 animations:animationBlock completion:^(BOOL finished) { 

    }]; 
}else{ 
    animationBlock(); 
} 

dass die Kopf

+0

dies würde nicht mit Keyframes funktionieren –

+0

Dies ist eine elegante Lösung. Vielen Dank. – GeneCode

18

Nach den Apple-docs vermeiden würde:

Wenn die Dauer der Animation 0 ist, wird dieser Block am Anfang durchgeführt der nächste Lauf-Schleifenzyklus.

+1

Also möglicherweise nicht 0 Verzögerungen von der Zeit die Animationsanweisung ausgeführt wird? – hzxu

+0

@hzxu genau. Der Effekt ist der gleiche wie beim Aufruf von '[self performSelector: @selector (animate) afterDelay: 0]' – chebur

+0

Ich kann bestätigen, dass dies tatsächlich der Fall ist. Die Verwendung von 0 ist nicht gleichbedeutend mit der Animation und sofortigen Ausführung. – strange

0

Sie können animateWithDuration Wert dynamisch nach Bedarf festlegen.

Wenn Sie 0 setzen, bedeutet dies, dass keine Animationsübergangszeit vorliegt. So wird View ohne Animation angezeigt. Wenn Sie eine Animation bereitstellen möchten, geben Sie einen Wert größer als 0 ein.

**float animationDurationValue=0.03f; 
     [UIView animateWithDuration:x delay:0.0f options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse 
animations:^{ 
          [yourView setFrame:CGRectMake(0.0f, 100.0f, 300.0f, 200.0f)]; 
         } 
         completion:nil];** 

Bitte lassen Sie mich wissen, wenn ein Problem.

2

Okay, ich habe weitere Beobachtungen dazu. Erstens gibt es einen Leistungs-Overhead, wenn die Animation mit der Dauer null verwendet wird, aber der tiefere Unterschied besteht darin, dass der Abschlussblock der Animation asynchron gehandhabt wird. Dies bedeutet, dass das erste Ausblenden und Anzeigen der Ansicht möglicherweise nicht zu dem von Ihnen erwarteten Ergebnis führt.

Also, nein, ich würde definitiv vorschlagen, nicht die Null als Dauer zu verwenden, da es nicht synchron ist.

1

Ich schrieb dieses kleine Swift Erweiterung um das Problem zu überwinden:

extension UIView { 

/// Does the same as animate(withDuration:animations:completion:), yet is snappier for duration 0 
class func animateSnappily(withDuration duration: TimeInterval, animations: @escaping() -> Swift.Void, completion: (() -> Swift.Void)? = nil) { 
    if duration == 0 { 
     animations() 
     completion?() 
    } 
    else { 
     UIView.animate(withDuration: duration, animations: animations, completion: { _ in completion?() }) 
    } 
} 
} 

Man kann es als Ersatz für UIView.animate(withDuration:animations:completion) verwenden können und hat keine Gedanken mehr über die Dauer machen 0.