【问题标题】:Block based KVO: Block-KVO vs THObserversAndBinders vs KVOController [closed]基于块的 KVO:Block-KVO vs THObserversAndBinders vs KVOController [关闭]
【发布时间】:2014-07-10 16:14:52
【问题描述】:

Block-KVO vs THObserversAndBinders vs KVOController

各有什么优缺点?哪个更好,为什么?

更新:最后,我倾向于使用Objective-Chain 来处理KVO。 ReactiveCocoa 也是一个选项,但可能太过分了。

【问题讨论】:

  • 你为什么对“基于块的 kvo”感兴趣? KVO 有什么问题需要块?
  • KVO 语法很丑,伙计。
  • 源代码都在了,后面两个我用过,最后差别不大,但是代码真的不多,我就拿一个看看你更喜欢哪一个。
  • 太糟糕了,问题被关闭了。快速调查显示以下内容。 Block-KVO 有一个reacher 接口(它显式地提供值)并支持单向和双向映射; THObserversAndBinders 支持绑定; KVOController 没有。另一方面,KVOController 和 THObserver 在 dealloc 时会自动删除观察结果,但我在 Block-KVO 中找不到类似的功能(您必须手动删除观察者)。 JFYI 还有简单的KeyValueObserver
  • 当 SO 像这样结束良好的讨论时让我发疯。

标签: ios objective-c key-value-observing


【解决方案1】:

首先,我只想说这是一个主观问题的典型例子,可能不应该问here——你显然是这里的一个成熟的成员,我相信你已经知道了。

但是既然你问了,我会尽量不主观地回答你的主观问题——虽然这对 Stack Overflow 来说不是最好的问题,但总的来说这是一个很好的问题,我相信一些 Google 员工最终会回答在这里寻找答案,主观与否!


首先,如果您对 KVO 的唯一/主要抱怨是语法(正如您在对问题的评论中提到的那样),不要选择 Objective-Chain 或其灵感,ReactiveCocoa。虽然它们有大量的usefulness,但它们的重量或复杂性都不值得仅仅为了更易于访问的KVO 语法。

在你一开始提到的三个库中,弹出最多的一个是KVOController——在简单的语法和对线程安全的坦率之间,你可以让大量的 GitHub 明星为自己说话。 这是我对最初发布的三个选项的推荐

其他选项,看起来也很轻巧,语法很好,也有自己的优点——Block-KVO 是三个选项中唯一一个使用 MIT 许可证而不是 BSD 的选项,所以如果这是必要的偏好对于您的项目,请牢记这一点——THObserversAndBinders 尽管自 2013 年底以来没有更新,但它具有出色的文档和缺乏 Facebook 所有权,如果这也是您的事的话。


希望这会给你一个客观的列表来帮助你选择最好的选择——并且确保下次不要那么开放:)

【讨论】:

  • 感谢您的回答。我反对 SO 的政策,即不能就 X 与 Y 的比较提出问题;这是因为过去我发现 SO 的比较答案非常有用(在许多情况下,它是比较 X 和 Y 的唯一来源)。所以我正在颠覆内部的系统,并试图改变政策。 :D 我在基于块的 KVO 上进行了大量谷歌搜索,但找不到任何合适的比较(而且我自己也没有时间查看这三个项目的代码)。无论如何,不​​用担心,我认为我不会很快提出开放式问题。
  • 但无论如何,正如我所提到的,我倾向于使用 Objective-Chain。我想尝试使用它的一些附加功能(例如基于块的通知以及连接不同对象的两个属性并在它们之间进行转换)。
【解决方案2】:

这是一个最小的工作想法(我也对 KVO 风格感到厌烦)。想法是在 KVO 上下文中携带块,然后在触发观察时调用它。

//  NSObject+KVOBlock.h

#import <Foundation/Foundation.h>

@interface NSObject (KVOBlock)

// invoke the block when the receiver's value at keyPath changes
// block params are the receiver, the keyPath and the old value
- (void)observeKeyPath:(NSString *)keyPath withBlock:(void (^)(id, NSString *, id))block;
- (void)unobserveKeyPath:(NSString *)keyPath;

@end

//  NSObject+KVOBlock.m

#import "NSObject+KVOBlock.h"

@implementation NSObject (KVOBlock)

- (void)observeKeyPath:(NSString *)keyPath withBlock:(void (^)(id, NSString *, id))block {   
    [self addObserver:self forKeyPath:keyPath
              options:NSKeyValueObservingOptionOld
              context:(__bridge void *)(block)];
}

- (void)unobserveKeyPath:(NSString *)keyPath {

    [self removeObserver:self forKeyPath:keyPath];
}

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {

    void (^block)(id, NSString *, id) = (__bridge void (^)(id, NSString *, id))context;
    block(self, keyPath, [change objectForKey:NSKeyValueChangeOldKey]);
}

@end

这样称呼...

// assume a class called SomeObject with an instance called someObject
someObject.someProperty = @"Bar";

[someObject observeKeyPath:@"someProperty" withBlock:^(SomeObject *object, NSString *keyPath, NSString *oldValue) {

    // avoid referring directly to 'someObject' in this block, since it retains
    // the block via the kvo context, thereby causing a retain cycle.  The first
    // param ('object') is exactly equal to someObject. So use that instead.

    NSLog(@"object=%@, keyPath=%@, oldValue=%@, newValue=%@",
        object, keyPath, oldValue, object.someProperty);
}];

// at any point after this, when you change someProperty, the block will be invoked 
self.object.someProperty = @"Foo";

我用上面的代码做了一个小测试,并确认它至少在此处显示的情况下有效。控制台输出看起来像这样...

<SomeObject :0xblahblah>, keyPath=someProperty, oldValue=Bar, newValue=Foo

【讨论】:

  • 感谢您的回答。这是对 context 参数的一个很好的使用。很遗憾我不能分割声望赏金,我很想给你一些。 :-(
  • 我希望没有人尝试使用此代码。在这样的类别中覆盖常用功能必然会产生问题。如果 NSObject 的某些未来实现也在内部使用 KVO 怎么办?繁荣。
猜你喜欢
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多