80 votes

Utiliser la Valeur de la Clé de l'Observation pour obtenir un KVO de rappel sur une UIView du cadre

Je veux regarder en UIViews' frame, bounds ou center de la propriété. Comment puis-je utiliser la Clé-Valeur d'Observation pour y parvenir?

73voto

hfossli Points 6815

Il y a généralement des notifications ou d'autres événements observables où KVO n'est pas pris en charge. Même si les docs dit "non", il est apparemment en sécurité à observer les CALayer la sauvegarde de la UIView. L'observation de la CALayer fonctionne dans la pratique en raison de son utilisation intensive de KVO et bon accesseurs (au lieu de ivar de manipulation). Il n'est pas garanti pour fonctionner à l'avenir.

De toute façon, le point de vue de l'image est juste le produit d'autres propriétés. Donc nous avons besoin d'observer ces

[view addObserver:self forKeyPath:@"frame" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"bounds" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"transform" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"position" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"zPosition" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"anchorPoint" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"anchorPointZ" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"frame" options:0 context:NULL];
[view.layer addObserver:self forKeyPath:@"transform" options:0 context:NULL];

Voir l'exemple complet ici https://gist.github.com/hfossli/7234623

REMARQUE: Ce n'est pas dit pour être pris en charge dans les docs, mais il fonctionne aujourd'hui avec toutes les versions d'iOS à ce jour (actuellement iOS 2 -> iOS 8 GM)

63voto

hfossli Points 6815

EDIT: je ne pense pas que cette solution est assez approfondie. Cette réponse est gardé pour des raisons historiques. Voir mon nouveau réponse ici: http://stackoverflow.com/a/19687115/202451


Vous avez à faire, KVO sur le cadre-de la propriété. "auto" est dans ce cas un UIViewController.

l'ajout de l'observateur (généralement dans viewDidLoad):

[self addObserver:self forKeyPath:@"view.frame" options:NSKeyValueObservingOptionOld context:NULL];

retrait de l'observateur (généralement dans dealloc ou viewDidDisappear:):

[self removeObserver:self forKeyPath:@"view.frame"];

Obtention d'informations sur le changement

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if([keyPath isEqualToString:@"view.frame"]) {
        CGRect oldFrame = CGRectNull;
        CGRect newFrame = CGRectNull;
        if([change objectForKey:@"old"] != [NSNull null]) {
            oldFrame = [[change objectForKey:@"old"] CGRectValue];
        }
        if([object valueForKeyPath:keyPath] != [NSNull null]) {
            newFrame = [[object valueForKeyPath:keyPath] CGRectValue];
        }
    }
}

 

7voto

Nikolai Ruhe Points 45433

Actuellement, il n'est pas possible d'utiliser KVO d'observer une vue de l'image. Propriétés doivent être KVO conformes à être observables. Malheureusement, les propriétés de la UIKit cadre sont généralement pas observables, comme avec tout autre système de cadre.

À partir de la documentation:

Remarque: Bien que les classes du framework UIKit ne supportent généralement pas KVO, vous pouvez toujours le mettre en œuvre dans les objets personnalisés de votre application, y compris les vues personnalisées.

Il y a quelques exceptions à cette règle, comme NSOperationQueue de l' operations de la propriété, mais ils doivent être explicitement décrite.

Même si l'aide de KVO sur une vue des propriétés pourraient actuellement le travail je ne recommande pas de l'utiliser dans le code de la navigation. C'est un fragile approche et s'appuie sur les sans-papiers comportement.

4voto

Tommy Points 56749

Si je peux contribuer à la conversation: comme d'autres l'ont souligné, frame n'est pas garantie à clé-valeur de l'observable lui-même et ne sont ni l' CALayer propriétés, même si elles semblent être.

Ce que vous pouvez faire à la place est de créer un personnalisé, UIView sous-classe qui remplace setFrame: , et annonce que la réception d'un délégué. Définir l' autoresizingMask , de sorte que le point de vue a flexible tout. Le configurer pour être totalement transparent et de petite taille (pour économiser des coûts sur l' CALayer sauvegarde, non pas que cela importe beaucoup) et de l'ajouter en tant que sous-vue de la vue que vous souhaitez regarder les changements de taille.

Cela a fonctionné avec succès pour moi le chemin du retour sous iOS 4 lorsque nous avons été les premiers en précisant iOS 5 comme l'API de code et, par conséquent, besoin temporaire d'émulation de l' viewDidLayoutSubviews (bien que primordial layoutSubviews a été plus approprié, mais vous obtenez le point).

-4voto

saky Points 19

Il n'est pas sûr d'utiliser KVO dans certains UIKit les propriétés comme l' frame. Ou du moins c'est ce qu'Apple a dit.

Je vous conseille d'utiliser ReactiveCocoa, cela vous aidera à écouter des changements dans toute la propriété, sans l'aide de KVO, il est très facile de commencer à observer quelque chose à l'aide de Signaux:

[RACObserve(self, frame) subscribeNext:^(CGRect frame) {
    //do whatever you want with the new frame
}];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X