“现代”Objective-C中的综合和受保护实例变量?

时间:2014-10-07 00:24:35

标签: objective-c macos inheritance ivar synthesize

我想创建一个类作为基类(或#34; abstract")类,由子类扩展。我能解释我所说的最好的方法就是举几个例子。这是我的超类的可能接口:

#import <Cocoa/Cocoa.h>
#import "MyViewControllerDelegate.h"

@interface MyViewController : NSViewController

@property (nonatomic, weak) id<MyViewModeControllerDelegate> delegate;
@property (nonatomic, copy) NSArray *content;

@end

这样写它似乎很干净,但我无法从我的子类访问ivars。

在做了一些研究后,我得出结论,提供直接访问ivars的子类的好方法是使用@protected指令并在头文件中包含任何声明,以便子类可以看到它:

#import <Cocoa/Cocoa.h>
#import "MyViewControllerDelegate.h"

@interface MyViewController : NSViewController {
@protected
    __weak id<MyViewControllerDelegate> _delegate;
    NSMutableArray *_content;
}

@property (nonatomic, weak) id<BSDViewModeControllerDelegate> delegate;
@property (nonatomic, copy) NSArray *content;

@end

我个人对此没有任何问题,它似乎按我想要的方式工作(例如,子类可以直接访问ivars,但其他类必须使用访问器)。但是,我每天都会阅读博客文章或Stack Overflow答案,说明实例变量应该只是合成,或者“我甚至不再触摸实例变量”。&#34;

问题是,我开始学习ARC后的Objective-C,所以我并不完全了解开发人员过去做事的方式。我个人喜欢我实现自己的getter / setter时的控件,我喜欢能够实际实例变量声明,但也许我是老学校。我的意思是,如果一个人应该&#34;让编译器合成实例变量,&#34;如何包含任何类型的逻辑或副作用&#34;没有实现一堆KVO?

例如,如果合成了我的实例变量和getter / setter,我该如何懒惰地初始化东西?例如,我有时喜欢这样做:

- (NSArray *)myLazyArray
{
    if ( _myLazyArray == nil ) {
        self.myLazyArray = @[];
    }
    return _myLazyArray.copy;
}

或者如何确保设置的值与当前设置的值不相同?我有时会在我的mutator方法中执行检查,如下所示:

- (void)setMyLazyArray:(NSArray *)array
{
    if ( [array isEqualToArray:_myLazyArray] )
        return;
    _myLazyArray = array.mutableCopy;
}

我已经阅读了Apple的所有文档,但是他们的一半文档可以追溯到2008年(或者在某些情况下更糟),所以我并不完全确定它们是最好的获取有关此事的信息。

我想我的问题的主旨是:有一个首选的&#34;现代&#34;在Objective-C中处理实例变量,变量合成,继承,范围等的方法?不包含答案的奖励积分&#34; Bro,Swift。&#34;或者&#34;你没有使用Swift?&#34;

非常感谢任何指导。谢谢你的阅读!

1 个答案:

答案 0 :(得分:2)

为什么你的子类需要访问你的ivars? Ivars是一个实现细节,子类不应该关注它。如果父类在属性setter / getters中执行逻辑,则可能存在各种副作用。因此,请始终通过财产访问它们。

假设这是在您的子类中,并且您正在覆盖属性getter:

- (NSArray *)myLazyArray
{
    if ( super.myLazyArray == nil ) {
        // do what you need to do to populate the array
        // assign it to yourself (or super)
        self.myLazyArray = @[];
    }

    return super.myLazyArray;
}

然后对于二传手:

- (void)setMyLazyArray:(NSArray *)array
{
    if ( [array isEqualToArray:super.myLazyArray] )
        return;
    super.myLazyArray = array.mutableCopy;
}