iphone - 如何进行键值观察并在 UIView 的框架上获取 KVO 回调?

我想观察 UIViewframeboundscenter 属性的变化。如何使用 Key-Value Observing 来实现这一点?

最佳答案

通常存在不支持 KVO 的通知或其他可观察事件。即使文档说 'no',观察支持 UIView 的 CALayer 表面上是安全的。观察 CALayer 在实践中是有效的,因为它广泛使用了 KVO 和适当的访问器(而不是 ivar 操作)。不能保证继续工作。

无论如何, View 的框架只是其他属性的产物。因此我们需要观察那些:

[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)

注意:请注意,在它达到最终值之前,您将收到多个回调。例如,更改 View 或图层的框架将导致图层更改 positionbounds(按此顺序)。


使用 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");
}];

https://stackoverflow.com/questions/4874288/

相关文章:

iphone - 如何覆盖@synthesized getter?

objective-c - 加载 UIPickerView 后选择行

objective-c - iOS 8 iPhone 上的 UIPopoverPresentatio

iphone - 在 Xcode 4 中将静态库链接到 iOS 项目

ios - UICollectionView中的左对齐单元格

objective-c - 在 iOS 8 应用程序中隐藏状态栏

objective-c - 在 Iphone UIImageView 中添加动画 Gif 图像

ios - UITextView 从文本的底部或中间开始

iphone - UIBarButtonItem : target-action not worki

ios - 检查 key 是否存在于 NSDictionary 中