Xcode 4.5中@property和ivar的区别

12

之前我一直看到使用属性和实例变量的例子是这样的...

在SomeClass.h文件内

@interface SomeClass : NSObject {
    NSString *_someString;
}

@property NSString *someString;

@end

然后,在 SomeClass.m 中:

#import "SomeClass.h"

@implementation SomeClass

@synthesize someString = _someString;

@end

最近(在WWDC 2012视频中)我听说我们不再需要@synthesize,而是建议仅使用@property而不使用其相关联的iVar。

因此,上述内容将变为...

SomeClass.h

@interface SomeClass : NSObject

@property NSString *someString;

@end

SomeClass.m

#import "SomeClass.h"

@implementation SomeClass

@end

这只是使用了 @property 而没有使用 ivar。这样做很合理,我也一直在使用。

但是,我也看到过一些例子...

SomeClass.h

@interface SomeClass : NSObject

@end

SomeClass.m

#import "SomeClass.h"

@interface SomeClass () {
    NSString *someString;
}

@end

@implementation SomeClass

@end

这里只有一个私有的iVar,没有@property

那么有什么区别呢?我知道@property还提供了访问器方法,但你不必重写访问器方法。你可以使用默认访问器。

那么什么情况下应该使用@property而不是ivar,什么情况下应该只使用ivar而不是@property?为什么不完全放弃ivar,只使用@properties呢?如果它们需要是私有的,则只需在.m中的接口扩展中使用它们。

快速编辑以回答关于内存管理的答案。我正在使用ARC,对我来说,使用strongweak@properties比使用ivars更能控制内存管理。

希望问题表述清楚。

谢谢


请注意,您上面的第一个示例是错误的。在其中,您有一个名为someString的属性,具有默认的后备iVar命名为_someString,以及第二个iVar与该属性没有任何关联,但仅为了引起痛苦而被命名为someString。 :-) - Phillip Mills
@Phillip Mills,我已经纠正了。 - Fogmeister
1
@property 使您能够在普通 iVar 无法使用 KVO 的情况下使用它。除了您已经提到的之外,我不知道还有什么其他优缺点。 - Tim Reddy
因此,两者都可以访问相同级别的内存管理。iVars没有getter和setter,而属性有。属性允许使用KVO,而iVars则不行。那我就坚持使用属性吧 :D - Fogmeister
2个回答

2
一般情况下,您总是可以使用属性。如果您有“assign”属性,则可以使用ivar,因为在getter / setter中不需要任何内存管理。但是,如果您应该保留对象,那么使用ivar就很不方便,因为您必须手动保留/释放它们,而属性会自动完成这些操作。
此外,如果您使用ivar,则无法控制设置/获取值。通常使用公共字段而不是getter或setter是一种不好的做法。例如,如果您可以为存储人的年龄的字段设置负值,则不行。
并且您无法使用KVO与ivar。

但如果我使用ARC,那么所有这些都会自动完成。对我来说,似乎使用具有强和弱属性的属性可以让我更好地控制内存,而无需使用iVars。 - Fogmeister
你可以使用 __weak NSString* _string 来达到与 @property (weak) NSString* string 相同的控制水平。 - Tim Reddy
2
  1. 如果您使用ivars,则无法控制设置/获取值。通常,使用公共字段而不是getter或setter是一种不好的做法。例如,如果您可以为存储人的年龄的字段设置负值,则不可以。
  2. 您无法使用KVO与ivars。
- igoris
谢谢,我想我还是会坚持使用 @properties :D 我本来就有这个想法,但我认为从这里得到的回复已经确认了我的决定 :D - Fogmeister
我更新了我的答案,加入了来自我的评论的信息,以涵盖属性的更多优点:) - igoris
我认为你对属性和ARC之间的关系完全错误。ARC在ivar上的工作方式与在属性上相同。当ARC打开时,您不再对任何东西调用retain/release,包括ivar。如果您尝试这样做,将会收到编译器警告。 - Philip007

-1

我认为这取决于你是否可以使用"->"语法访问公共实例变量。

也许以前,如果你声明了一个只读属性而没有使用@private实例变量,你可以使用"->"语法访问它的实例变量(也许这会破坏封装性)。

但是现在,如果你像这样声明:

{
@private NSArray *a;
@protected NSArray *b;
@public NSArray *c;
}
@property (nonatomic, retain) NSArray *d; 

你只能通过 "->" 访问 "c" 实例变量,尝试使用以下代码。 使用 a、b 和 d 会出现警告或错误。

如果这对你有所帮助,我会很高兴。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接