gpt4 book ai didi

Objective-C:正确处理子类 NSControl 和 NSActionCell 之间的共享属性?

转载 作者:搜寻专家 更新时间:2023-10-30 20:09:13 24 4
gpt4 key购买 nike

我一直不确定的一件事是如何正确处理自定义 NSControl 之间的通信。子类和 NSCell子类。在我对 Cocoa 的介绍中,我多次看到它提到父控件如何提供许多与子单元格/单元格实现相同的方法、访问器和修改器。例如,NSControl类和 NSCell类(class)都有-isEnabled-setEnabled:在他们的头文件中:

NSControl.h

- (BOOL)isEnabled;
- (void)setEnabled:(BOOL)flag;

NSCell.h
- (BOOL)isEnabled;
- (void)setEnabled:(BOOL)flag;

我了解 NSControl类为 NSCell 中的大多数属性提供“覆盖”方法。 .我更感兴趣的是:它们是如何实现的?或者更好的是,应该如何实现他/她自己的子类的共享属性?显然,只有 Apple 的工程师才真正知道他们的框架内部发生了什么,但我想也许有人可以阐明以一种非常干净的方式模仿 Apple 的覆盖方法方法的最佳方法。

我在解释东西方面很糟糕,所以我将提供一个例子来说明我在说什么。假设我已经继承了 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 的属性。 .

我的问题是:有效保持控件和单元格之间的共享属性同步的标准方法是什么?这似乎是一个主观问题,我想是的,但我想认为大多数时候都有“最好的方法”来做到这一点。

过去我使用过各种不同的方法,但我想缩小我处理它的方式,并且只使用能够以最低开销提供最佳数据完整性的技术。我应该使用绑定(bind)吗?实现调用其对应方匹配方法的自定义更改器(mutator)怎么样? KVO?我是一个失败的原因吗?

以下是我过去做过的一些事情(其中一些或全部可能完全古怪或直接错误):
  • cocoa 绑定(bind) — 我只是将控件的属性绑定(bind)到单元格的属性(反之亦然):
    [self bind:@"sharedProp" toObject:self.cell withKeyPath:@"sharedProp" options:nil];

    这似乎是一个很好的方法,但是您将绑定(bind)到/从哪个对象?我已经阅读了所有的 KVO/KVC/Bindings 文档,但是当属性在任何一种情况下都应该相同时,我从来没有真正意识到绑定(bind)方向性的重要性。有一般规律吗?
  • 发送来自 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每个共享属性(property)的声明。根据观察,我也发送了通知,但由于控制单元关系是尽可能“一对一”的(甜蜜的双关语),这看起来很愚蠢。

  • 同样,我知道这有点主观,但我真的很感激一些指导。我学习 Cocoa/Objective-C 已经有一段时间了,这从一开始就困扰着我。了解其他人如何处理控件和单元格之间的属性同步真的可以帮助我!

    谢谢!

    最佳答案

    首先要注意NSCell主要是因为 NeXT 时代的性能问题而存在。从 NSCell 迁移缓慢,并且您通常不应该创建新的,除非您需要与需要它们的东西进行交互(例如使用 NSMatrix ,或者如果您正在做一些看起来很像 NSMatrix 的事情)。请注意对 NSTableView 的更改从 10.7 开始淡化单元格,以及如何NSCollectionViewItem是一个全 View Controller 。我们现在有能力在大部分时间只使用 View 而不需要 NSCell .

    也就是说,通常控制只是将消息转发到单元格。例如:

    - (BOOL)sharedProp {
    return self.cell.sharedProp;
    }

    - (void)setSharedProp:(BOOL)sharedProp {
    [self.cell setSharedProp:sharedProp];
    }

    如果 KVO 是一个问题,您仍然可以使用 keyPathsForValuesAffectingValueForKey: 连接它(及其亲属)。例如,您可以执行以下操作:
    - (NSSet *)keyPathsForValuesAffectingSharedProp {
    return [NSSet setWithObject:@"cell.sharedProp"];
    }

    那应该让你观察 sharedProp并将更改透明地转发到 cell.sharedProp .

    关于Objective-C:正确处理子类 NSControl 和 NSActionCell 之间的共享属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21841285/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com