Jak natychmiast przenieść CALayer (bez animacji)

80

Próbuję przeciągnąć CALayerw aplikacji na iOS.

Jak tylko zmienię właściwość position, próbuje animować do nowej pozycji i miga w każdym miejscu:

 layer.position = CGPointMake(x, y)

Jak mogę CALayersnatychmiast się przenieść ? Nie mogę się rozejrzeć po interfejsie API Core Animation.

Mel
źródło
w odniesieniu do tej bardzo starej kontroli jakości, krytyczny problem na dzień dzisiejszy jest następujący: stackoverflow.com/a/56980329/294884
Fattie,

Odpowiedzi:

168

Chcesz zakończyć rozmowę w następujący sposób:

[CATransaction begin]; 
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
layer.position = CGPointMake(x, y);
[CATransaction commit];
Ben Gottlieb
źródło
1
To jest dokładnie to. Nawet nie pomyślałem o CATransaction. Wielkie dzięki!
Mel
5
Tak, 6 i pół roku później. Wciąż pomocny. : D
Fogmeister
1
iOS7 obsługuje nowe skróty:[UIView performWithoutAnimation:<#^(void)actionsWithoutAnimation#>];
k06a
2
7 lat, 7 miesięcy i 17 dni później: nadal pomocne. Dzięki!
kanobius
1
kciuk w górę 9 lat później
nshuman
32

Rozszerzenie Swift 3:

extension CALayer {
    class func performWithoutAnimation(_ actionsWithoutAnimation: () -> Void){
        CATransaction.begin()
        CATransaction.setValue(true, forKey: kCATransactionDisableActions)
        actionsWithoutAnimation()
        CATransaction.commit()
    }
}

Stosowanie :

CALayer.performWithoutAnimation(){
    someLayer.position = newPosition
}
CryingHippo
źródło
1
Przydatne jest dodanie @noescapeatrybutu do bloku, aby zezwolić (i wyjaśnić), że selfnie jest potrzebny w bloku
Andrew
22

Możesz także skorzystać z funkcji komfortowej

[CATransaction setDisableActions:YES] 

także.

Uwaga: koniecznie przeczytaj komentarze Yogeva Shelly, aby zrozumieć wszelkie pułapki, które mogą wystąpić.

Biclopy
źródło
5
Ważne, ma to wpływ na wszystkie CALayer, więc chcesz ponownie włączyć akcje po zakończeniu, np. [CATransaction setDisableActions: YES]
Yogev Shelly
Cholera, powinienem to powiedzieć. Dobra obrona. Polecenie wyłącza animacje, dopóki nie zostanie ustawione na NIE lub dopóki główny silnik animacji graficznej nie zakończy cyklu pracy. Nie jestem pewien, czy to właściwe słowo: / Ale dziękuję za wyjaśnienie tego wszystkim.
Biclops,
15

Jak sugerowali inni, możesz użyć CATransaction.
Problem pojawia się, ponieważ CALayer ma domyślny niejawny czas trwania animacji wynoszący 0,25 sekundy.

W związku z tym łatwiejszą (moim zdaniem) alternatywą setDisableActionsjest użycie setAnimationDurationz wartością 0.0.

[CATransaction begin];
[CATransaction setAnimationDuration:0.0];
layer.position = CGPointMake(x, y);
[CATransaction commit];
Więc to skończone
źródło
Łatwe do zapamiętania, łatwe do zrozumienia podczas ponownego czytania kodu i łatwiejsze do wpisania. Dzięki!
Pan T
3

Łącząc poprzednie odpowiedzi tutaj dla Swift 4, aby wyraźnie określić czas trwania animacji ...

extension CALayer
{
    class func perform(withDuration duration: Double, actions: () -> Void) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(duration)
        actions()
        CATransaction.commit()
    }
}

Stosowanie...

CALayer.perform(withDuration: 0.0) {
            aLayer.frame = aFrame
        }
Giles
źródło