Обычно есть уведомления или другие наблюдаемые события, где KVO не поддерживается.Хотя в документах написано 'нет' , якобы безопасно наблюдать за CALayer, поддерживающим UIView.Наблюдение за CALayer работает на практике из-за его широкого использования KVO и надлежащих средств доступа (вместо манипуляций с ivar).В будущем работа не гарантируется.
В любом случае, рамка представления является просто продуктом других свойств.Поэтому мы должны соблюдать следующие правила:
[self.view addObserver:self forKeyPath:@"frame" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"bounds" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"transform" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"position" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"zPosition" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"anchorPoint" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"anchorPointZ" options:0 context:NULL];
[self.view.layer addObserver:self forKeyPath:@"frame" options:0 context:NULL];
См. Полный пример здесь https://gist.github.com/hfossli/7234623
ПРИМЕЧАНИЕ. Это не поддерживается в документах, но на сегодняшний день оно работает со всемиВерсии для iOS на данный момент (в настоящее время iOS 2 -> iOS 11)
ПРИМЕЧАНИЕ. Имейте в виду, что вы получите несколько обратных вызовов до того, как он установит свое окончательное значение.Например, изменение кадра вида или слоя приведет к изменению слоя position
и bounds
(в этом порядке).
С ReactiveCocoa вы можете сделать
RACSignal *signal = [RACSignal merge:@[
RACObserve(view, frame),
RACObserve(view, layer.bounds),
RACObserve(view, layer.transform),
RACObserve(view, layer.position),
RACObserve(view, layer.zPosition),
RACObserve(view, layer.anchorPoint),
RACObserve(view, layer.anchorPointZ),
RACObserve(view, layer.frame),
]];
[signal subscribeNext:^(id x) {
NSLog(@"View probably changed its geometry");
}];
И если вы хотите знать только, когда bounds
меняется, вы можете сделать
@weakify(view);
RACSignal *boundsChanged = [[signal map:^id(id value) {
@strongify(view);
return [NSValue valueWithCGRect:view.bounds];
}] distinctUntilChanged];
[boundsChanged subscribeNext:^(id ignore) {
NSLog(@"View bounds changed its geometry");
}];
И еслихочу знать только когда frame
изменения можно сделать
@weakify(view);
RACSignal *frameChanged = [[signal map:^id(id value) {
@strongify(view);
return [NSValue valueWithCGRect:view.frame];
}] distinctUntilChanged];
[frameChanged subscribeNext:^(id ignore) {
NSLog(@"View frame changed its geometry");
}];