La désactivation de l'implicite animations -[CALayer setNeedsDisplayInRect:]
J'ai une couche avec certains complexes, le code de dessin dans son drawInContext: la méthode. J'essaie de minimiser la quantité de dessin que j'ai besoin de le faire, donc je suis aide -setNeedsDisplayInRect: pour la mise à jour, le changement de pièces. Cela fonctionne magnifiquement. Toutefois, lorsque le système graphique des mises à jour de ma couche, c'est la transition de l'ancienne à la nouvelle image à l'aide d'un cross-fade. J'aimerais qu'il basculer instantanément.
J'ai essayé d'utiliser CATransaction pour désactiver les actions et définir la durée à zéro, et ne travaillent pas. Voici le code que j'utilise:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
Est-il une autre méthode sur CATransaction je devrait utiliser à la place (j'ai aussi essayé -setValue:forKey: avec kCATransactionDisableActions, même résultat).
- vous pouvez le faire dans la prochaine exécution de la boucle:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
- J'ai trouvé beaucoup de réponses ci-dessous à travailler pour moi. Également utile de Apple est l'Évolution d'une Couche Comportement par Défaut document, qui décrit l'implicite de l'action de processus de prise de décision dans le détail.
- C'est une double question à celui-ci: stackoverflow.com/a/54656717/5067402
Vous devez vous connecter pour publier un commentaire.
Vous pouvez le faire en définissant les actions de dictionnaire sur le calque de retour
[NSNull null]
comme une animation pour la clé appropriée. Par exemple, j'utilisepour désactiver fade in /out animations à l'insertion ou à un changement de sous-couches à l'intérieur de l'un de mes couches, ainsi que des changements dans la taille et le contenu de la couche. Je crois que le
contents
clé est celui que vous cherchez, afin de prévenir le fondu enchaîné sur la mise à jour du dessin.Swift version:
@"position"
clé.@"hidden"
propriété dans l'action du dictionnaire de trop si vous êtes le basculement de la visibilité d'un calque de cette façon et souhaitez désactiver l'opacité de l'animation.-animationForKey:
et de voir quelles sont les touches qui sont animés en réponse à une action.actionForKey:
à la place), la découverte defontSize
,contents
,onLayout
etbounds
. Il semble que vous pouvez spécifier n'importe quelle touche vous pouvez utiliser dans lasetValue:forKey:
méthode, en fait précisant complexe chemins de clé commebounds.size
.NSStringFromSelector(@selector(contents))
, qui au moins a certains compiler le temps de vérifier. Le vôtre est beaucoup mieux. Pourrait le Brad de mise à jour de la réponse à inclure ce? Je suis heureux de le modifier, mais les grandes améliorations de ce genre sont souvent rejetées dans la modération.kCAOnOrderIn
,kCAOnOrderOut
&kCATransition
. Donc, Brad pouvez probablement laisser la réponse comme il est.Aussi:
//foo
avec[self setNeedsDisplayInRect: rect]; [self displayIfNeeded];
pour répondre à la question d'origine.[CATransaction setDisableActions:YES]
[CATransaction setDisableActions:YES]
est un raccourci pour tout le[CATransaction setValue:forKey:]
ligne. Vous avez encore besoin de labegin
etcommit
lignes.Lorsque vous modifiez la propriété d'une couche, CA crée habituellement une transaction implicite de l'objet à animer le changement. Si vous ne voulez pas pour animer le changement, vous pouvez désactiver implicite animations par la création d'une transaction explicite et l'établissement de ses kCATransactionDisableActions propriété vrai.
Objective-C
Swift
En plus de Brad Larson répondre: pour les couches (qui sont créés par vous-même) vous pouvez utiliser la délégation au lieu de modifier la couche d'
actions
dictionnaire. Cette approche est plus dynamique et peut être plus performant. Et il permet de désactiver toutes les implicites des animations sans avoir à énumérer tous les animables clés.Malheureusement, il est impossible d'utiliser
UIView
s comme couche personnalisée délégués, parce que chaqueUIView
est déjà un délégué de son propre calque. Mais vous pouvez utiliser une simple classe helper comme ceci:D'utilisation (à l'intérieur de la vue):
Il est parfois pratique d'avoir une vue d'contrôleur en tant que délégué pour de la vue personnalisée sous-couches; dans ce cas, il n'est pas nécessaire pour une classe d'assistance, vous pouvez mettre en œuvre
actionForLayer:forKey:
droit de la méthode à l'intérieur du contrôleur.Remarque importante: n'essayez pas de modifier le délégué de
UIView
s'couche sous-jacente (par exemple, pour activer implicite animations) — les mauvaises choses qui se passera 🙂Remarque: si vous souhaitez animer (pas de désactiver l'animation pour les) couche redessine, il est inutile de mettre
[CALayer setNeedsDisplayInRect:]
appel à l'intérieur d'unCATransaction
, car la redéfinition peut (et probablement) se produit parfois plus tard. La bonne approche consiste à utiliser les propriétés personnalisées, comme décrit dans cette réponse.CALayer
qui empêchaitnoImplicitAnimations
de travail. Peut-être que vous devez marquer votre propre réponse comme correcte et d'expliquer ce qui n'allait pas avec cette couche?CALayer
exemple (j'en ai eu deux à la fois).NSNull
ne pas mettre en œuvre laCAAction
protocole et ce n'est pas de protocole qui n'a que des méthodes optionnelles. Ce code bloque et vous ne pouvez même pas de le traduire à swift. Meilleure solution: Faire de votre objet conforme à laCAAction
protocole (avec un viderunActionForKey:object:arguments:
méthode qui ne fait rien) et retourself
au lieu de[NSNull null]
. Même effet, mais en toute sécurité (sans planter pour vous en assurer), et travaille également en Swift.CALayerDelegate
'sactionForLayer:forKey:
documentation des redirections).NSNull
t se conformer àCAAction
, voir la liste des protocoles, il est conforme à la référence (actuellement,CAAction
est le premier protocole dans la liste).CAAction
par un objet que vous avez le contrôle de l'affaire, bien que, mais je ne pense pas que c'est nécessaire, même en Swift. Je peux vous assurer que je n'avais pas un seul accident causé par un retourNSNull
de cette méthode. Aussi, je doute que Apple la documentation et des exemples suggère quelque chose qui pouvait provoquer un crash de votre application.NSNull
objet dans Swift, il suffit d'utiliserNSNull()
.NSNull
certainement n' PAS conforme à laCAAction
protocole. Lorsque j'essaie de revenirNSNull()
dans Swift, j'obtiens une erreur de compilation de me dire exactement ce que. Et quand j'ai lu le délégué de la documentation, il dit nulle part que vous pouvez retournerNSNull
. Voir aussi ici s33.postimg.org/si135uetr/... (où ton lien est moi) et ici, s33.postimg.org/j5a5ciegv/...layer?.actions = ["sublayers":NSNull(),"content":NSNull(),"onOrderOut":NSNull(),"bounds":NSNull(),"hidden":NSNull(),"position":NSNull()]//avoids implicit animation
Voici une solution plus efficace, semblable à accepté de répondre mais pour Swift. Pour certains cas, il sera mieux que la création d'une opération à chaque fois que vous modifiez la valeur qui est un souci de performances comme d'autres l'ont mentionné, par exemple: cas d'utilisation de glissement de la couche de position autour de à 60fps.
Voir apple docs pour comment la couche d'actions sont résolues. La mise en œuvre de la délégué sauter d'un niveau supplémentaire dans la cascade, mais dans mon cas c'était trop salissant, en raison de la avertissement au sujet du délégué besoin d'être mis à l'associé UIView.
Edit: mis à Jour grâce à l'intervenant en soulignant que
NSNull
est conforme àCAAction
.NullAction
pour Swift,NSNull
est conforme à laCAAction
déjà si vous pouvez faire la même chose que vous faites dans l'objectif C: couche.actions = [ "position" : NSNull() ]Basée sur Sam réponse, et de Simon difficultés... ajouter le délégué de référence après la création de la CSShapeLayer:
... ailleurs, dans la "m" fichier...
Essentiellement le même que Sam est sans la capacité de basculer via la commande "disableImplicitAnimations" variable arrangement. Plus de "bétonner" approche.
En fait, je n'ai pas trouvé de réponses à la droite. La méthode qui permet de résoudre le problème pour moi c'était ça:
Vous pouvez alors quelle que soit la logique en elle, pour désactiver une animation spécifique, mais depuis que j'ai voulu supprimé tous, je suis retourné à néant.
Trouvé une méthode plus simple pour désactiver l'action à l'intérieur d'un
CATransaction
qui appelle en internesetValue:forKey:
pour lakCATransactionDisableActions
clés:Swift:
Pour désactiver implicite de la couche d'animations dans Swift
disableActions()
comme son, comme c'est la même chose, mais c'est en fait pour obtenir la valeur actuelle. Je pense que c'est marqué@discardable
trop, rendant plus difficile à repérer. Source: developer.apple.com/documentation/quartzcore/catransaction/...Ajouter à votre classe personnalisée où vous êtes à la mise en place-méthode drawRect (). Apporter des modifications de code à la suite de vos besoins, pour moi, 'opacité' a fait le tour à l'arrêt de la croix-animation de fondu.
Si vous avez besoin d'une très rapide (mais il est vrai hacky) correction il pourrait être intéressant de faire juste (Swift):
De iOS 7 il y a une méthode de convenance qui fait juste cela:
Pour désactiver l'ennuyeux (floue) de l'animation lors du changement de la chaîne de propriété d'un CATextLayer, vous pouvez le faire:
et de l'utiliser ensuite comme (n'oubliez pas de configurer votre CATextLayer correctement, par exemple, la police, etc.):
Vous pouvez voir mon installation complète de CATextLayer ici:
Maintenant, vous pouvez mettre à jour caTextLayer.string comme beaucoup comme vous voulez =)
Inspiré par cette, et cette réponse.
De l'essayer.
Avertissement
Si vous définissez délégué de la UITableView exemple, il se produit parfois des crash.(Probablement le scrollview de hittest appelée récursivement.)
Mis à jour pour la swift et la désactivation d'un seul implicite de la propriété de l'animation dans iOS pas MacOS