KVO 检查 objective c 中 UIView 中所有子视图的 clipsToBounds 的变化

KVO check for change of clipsToBounds of all subviews in an UIView in objective c

我正在尝试为我的 UIView 中所有子视图的 clipsToBounds 属性 实现一个 KVO 示例。我不太明白如何更改 observeValueForKeyPath 方法中的值。我正在使用此代码:

-(void)ViewDidLoad{
        [self.navigationController.view addObserver:self forKeyPath:@"clipsToBounds" options:NSKeyValueObservingOptionNew |
         NSKeyValueObservingOptionOld context:nil];
    }
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"Triggered...")
    }

每当我更改我拥有的 UIView 中存在的子视图的 属性 clipToBounds 时,它就会被触发。对于发生的每个触发器,我都需要将值改回 false。我应该在 observeValueForKeyPath 中写什么来更改 clipsToBounds 属性?任何帮助表示赞赏。

当然添加观察者必须在它工作之前完成。 猜测您在“ViewDidLoad”中的拼写错误永远不会被调用,因为它应该是“viewDidLoad”。 除此之外,您的 KVO 模式可能看起来像..

static void *kvoHelperClipsToBounds = &kvoHelperClipsToBounds;

-(void)viewDidLoad {
    [self.navigationController.view addObserver:self forKeyPath:@"clipsToBounds" options:NSKeyValueObservingOptionNew context:&kvoHelperClipsToBounds];
}
    
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == kvoHelperClipsToBounds) {
        NSLog(@"context compared successful...");
        //be careful what you cast to.. i dont check isKindOf here.
        UINavigationBar* navbar = (UINavigationBar*)object;
        if (navbar.subviews.count > 1) {
            __kindof UIView *sub = navbar.subviews[1];
            if (sub.clipsToBounds) {
                dispatch_async(dispatch_get_main_queue(),^{
                    sub.clipsToBounds = NO;
                    [self.navigationItem.titleView layoutIfNeeded];
                });
            }
        }
    } 

    // or compare against the keyPath
    else if ([keyPath isEqualToString:@"clipsToBounds"]) {
        NSLog(@"classic Key compare Triggered...");
    }
    else
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}

[super observeValueForKeyPath...] 将无法识别的 keyPath 传递给 super 让 super 的 class KVO 工作,否则如果 super 的实现依赖于观察它们,这些将被忽略.如果需要,这还应该解释如何观察所有子视图。但是想一想,如果 UIView 的子 class 实现它并且所有子视图(或您喜欢的子视图)也将从这个特殊的子 class 继承,那么可能会有大量子视图触发 observeValueForKeyPath。

当您在观察它的 KVO 内部更改 clipsToBounds 时,您可能会调用一个循环,特别是当您同时观察旧值和新值时。你会改变 属性,属性 触发 kvo,kvo 改变 属性,属性 触发 kvo 等等。

设置[self.navigationController.view setClipsToBounds:YES]更改属性。但如果在 KVO 内部完成,它将再次触发 KVO,如前所述。 通常你会在 -initWithFrame:-initWithCoder: 中或通过 Interface Builder 设置 clipsToBounds 并且可能只是观察它是否被更改以适应其他代码。

旁注:上下文只需要是唯一的,以将其与其他 KVO 区分开来。它也可以是对真实对象指针的引用。

不要忘记在释放之前必须移除添加的观察者。