objective-C属性也定义为实例变量
我已经定义了objective-C属性也定义为实例变量,objective-c,properties,instance-variables,Objective C,Properties,Instance Variables,我已经定义了 @interface FooObject : NSObject @property (nonatomic, readonly) Foo *foo; @end 然后在实施过程中: @implementation FooObject { Foo *_foo; ... } 但是,我的理解是,创造财产 @property (nonatomic, readonly) Foo *foo; 在接口中,还创建 _foo 所以我的问题是,这样做有什么好处,可能的好处是什么。没有好处。只需删除
@interface FooObject : NSObject
@property (nonatomic, readonly) Foo *foo;
@end
然后在实施过程中:
@implementation FooObject {
Foo *_foo;
...
}
但是,我的理解是,创造财产
@property (nonatomic, readonly) Foo *foo;
在接口中,还创建
_foo
所以我的问题是,这样做有什么好处,可能的好处是什么。没有好处。只需删除
Foo*\u Foo代码>。在这种情况下是多余的。您会问:
这样做有什么好处吗
不,手动声明实例变量没有任何好处。事实上,这样做有一些缺点,因为您很容易输入错误的ivar名称(或错误地使用@synthesis
语句),最终得到两个ivar,一个是您手动创建的,另一个是为您合成的。它只是引入了可能的印刷错误导致难以诊断的bug的可能性
有几个注意事项:
这种手动定义IVAR以支持属性的模式有点过时,可以追溯到Objective-C编译器为您合成这些IVAR之前
值得注意的是,如果您使用的是旧的Objective-C编译器(例如,特别是那些在非macOS平台上试验Objective-C或使用旧版本的Xcode),编译器可能无法为您自动合成这些IVAR,您必须手动合成。尽管如此,您还是可以使用@synthesis
指令让编译器为您执行此操作,而不是手动声明ivar。只有在使用@synthesis
指令引入之前的极旧编译器时,才需要手动声明ivar
如果您自己实现了所有访问器方法(即只读属性的getter或读写属性的getter和setter),编译器将不会为您合成ivar。这种想法可能是,如果您正在编写自己的访问器方法,您可能会让那些访问器做一些与常规ivar交互以外的事情,因此它不会为您合成ivar
在这个场景中,如果需要,您必须自己手动合成ivar。例如,考虑这个类:
@interface Foo: NSObject
@property (nonatomic) NSInteger bar;
@end
如果同时实现两个访问器:
- (void)setBar:(NSInteger)bar {
// do something, and then update ivar
_bar = bar;
}
- (NSInteger)bar {
// do something, and then retrieve ivar
return _bar;
}
然后您必须自己在@实现中手动合成ivar:
@synthesize bar = _bar;
注意,我没有手动定义\u bar
ivar,但我还是让编译器来定义,但我必须使用@synthesis
指令手动启动它
我上面的示例具有读写属性。同样的问题也适用于只读属性,您已经为其实现了自己的自定义getter
显然,如果您没有实现自定义访问器方法(我们通常没有),您就不必手动合成ivar。只需定义@属性
,就完成了
还要确保在分机上为foo
设置readwrite
。因此,您可以在实现中设置它的值
@theCoderGuy-您可以这样做,但从技术上讲您不必这样做。您的@实现
理论上可以直接更新ivar,而不需要设置器。但我同意,当您有一个属性,希望在内部享受setter方法的好处,但不将其作为公共接口的一部分公开时,这是一个很好的模式。good point@Rob!如果您不打算使用setter,则不必强制使用:)