我一直不确定的一件事是如何正确处理自定义NSControl
子类和NSCell
子类之间的通信。在我对 Cocoa 的介绍中,我看到它多次提到父控件如何提供许多与子单元格/单元格实现相同的方法、访问器和修改器。例如,NSControl
类和类在它们的头文件中NSCell
都有-isEnabled
和:-setEnabled:
NSControl.h
- (BOOL)isEnabled;
- (void)setEnabled:(BOOL)flag;
NSCell.h
- (BOOL)isEnabled;
- (void)setEnabled:(BOOL)flag;
我了解NSControl
该类为. 我更感兴趣的是:它们是如何实现的?或者更好的是,应该如何实现他/她自己的子类的共享属性?显然,只有 Apple 的工程师才真正知道他们的框架内部发生了什么,但我想也许有人可以阐明以一种非常干净的方式模仿 Apple 的覆盖方法方法的最佳方法。NSCell
我在解释东西方面很糟糕,所以我将提供一个例子来说明我在说什么。假设我已经NSControl
像这样子类化了:
BSDToggleSwitch.h
#import "BSDToggleSwitchCell.h"
@interface BSDToggleSwitch : NSControl
@property (nonatomic, strong) BSDToggleSwitchCell *cell;
@property (nonatomic, assign) BOOL sharedProp;
@end
我已经分类了NSActionCell
:
BSDToggleSwitchCell.h
#import "BSDToggleSwitch.h"
@interface BSDToggleSwitchCell : NSActionCell
@property (nonatomic, weak) BSDToggleSwitch *controlView;
@property (nonatomic, assign) BOOL sharedProp;
@end
如您所见,它们都共享一个名为sharedProp
.
我的问题是:有效保持控件和单元格之间的共享属性同步的标准方法是什么?这似乎是一个主观问题,我想是的,但我想认为大多数时候都有“最好的方法”来做到这一点。
过去我使用过各种不同的方法,但我想缩小我处理它的方式,并且只使用能够以最低开销提供最佳数据完整性的技术。我应该使用绑定吗?实现调用其对应方匹配方法的自定义变异器怎么样?KVO?我是一个失败的原因吗?
以下是我过去做过的一些事情(其中一些或全部可能完全古怪或直接错误):
Cocoa Bindings - 我只是将控件的属性绑定到单元格的属性(反之亦然):
[self bind:@"sharedProp" toObject:self.cell withKeyPath:@"sharedProp" options:nil];
这似乎是一个很好的方法,但是您将绑定到/从哪个对象?我已经阅读了所有的 KVO/KVC/Bindings 文档,但是当属性在任何一种情况下都应该相同时,我从来没有真正意识到绑定方向性的重要性。有一般规律吗?
从 Mutators 发送消息- 我会从控件的 mutator 向单元格发送消息:
- (void)setSharedProp:(BOOL)sharedProp { if ( sharedProp == _sharedProp ) return; _sharedProp = sharedProp; [self.cell setSharedProp:sharedProp]; }
然后我会在单元的实现中做同样的事情:
- (void)setSharedProp:(BOOL)sharedProp { if ( sharedProp == _sharedProp ) return; _sharedProp = sharedProp; [self.controlView setSharedProp:sharedProp]; }
这似乎也相当合理,但似乎也更容易出错。如果一个对象在没有值检查的情况下向另一个对象发送消息,那么很容易发生无限循环,对吧?在上面的示例中,我为此添加了检查,但我确信有更好的方法。
观察和报告——我会观察每个对象实现中的属性变化:
static void * const BSDPropertySyncContext = @"BSDPropertySyncContext"; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ( context == BSDPropertySyncContext && [keyPath isEqualToString:@"sharedProp"] ) { BOOL newValue = [[change objectForKey:NSKeyValueChangeNewKey] boolValue]; if ( newValue != self.sharedProp ) { [self setSharedProp:newValue]; } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } }
再一次,这似乎是可行的,但我不喜欢
if
为每个共享属性写一个语句。根据观察,我也发送了通知,但由于控制单元关系是尽可能“一对一”的(甜蜜的双关语),这看起来很愚蠢。
同样,我知道这有点主观,但我真的很感激一些指导。我学习 Cocoa/Objective-C 已经有一段时间了,这从一开始就困扰着我。了解其他人如何处理控件和单元格之间的属性同步真的可以帮助我!
谢谢!