8

我们是否应该将我们希望保留的所有实例变量转换为私有属性,还是我遗漏了一些明显的东西?

@interface SomethingElse : Something  {

    NSMutableArray *someArray;

}

在此示例中, someArray 在具有 [NSMutableArray initWithObject:someObject] 的方法中被初始化,但未保留。

我的特殊情况是我正在更新游戏,有很多实例变量,所以我想确保我这样做是为了未来版本的 sdk。

4

6 回答 6

19

我们是否应该将我们希望保留的所有局部变量转换为私有属性,还是我遗漏了一些明显的东西?

首先,您在示例中显示的变量是实例变量,而不是局部变量。局部变量在代码块内声明(例如在函数或方法内,或在某些子块内,例如条件语句的主体内),并且其生命周期仅限于声明它们的块的执行. 实例变量在类中声明;该类的每个实例都有自己的该类声明的实例变量的副本。

其次,不,您不需要将所有实例变量都转换为属性。在 ARC 下,实例变量默认被视为强引用。属性实际上只是一个承诺,即类为某些访问器提供某些语义。仅仅拥有一个实例变量并不意味着您必须为该 ivar 提供访问器。(有些人可能会说你应该这样做,但你不必这样做。)

于 2012-07-03T16:12:03.793 回答
3

@property 与实例变量相同,除非您使用默认存储修饰符以外的其他修饰符,该修饰符对对象来说很强大。例如,如果您想@property (copy) NSString *s;使用实例变量并记得在每次设置变量时调用 copy,或者使用 @property(这更容易)。

于 2012-07-03T16:12:32.333 回答
1

ARC's version of retain is called strong.

Basically, you would declare it using something like:

@property (strong) NSMutableArray *someArray;

See What does the "strong" keyword do for details.

It's generally better to use properties instead of local variables, because the properties get you accessors/setters for "free", and are generally easier to use.

于 2012-07-03T16:02:30.330 回答
1

您在其他一些评论中描述了 BAD_ACCESS 问题。这里还有其他事情发生。在 ARC 中,除非有其他条件,否则您的 ivars 很强大(在非 ARC 中,它们不会代表您发布)。

例如,此 ARC 代码运行良好,没有 BAD_ACCESS,因为您在对其他答案的评论中报告:

@interface ArcTestViewController ()
{
    NSMutableArray *_someArray;
}
@end

@implementation ArcTestViewController

- (void)dealloc
{
    _someArray = nil;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    _someArray = [[NSMutableArray alloc] initWithObjects:@"Mo", @"Larry", @"Curly", nil];
}

- (IBAction)checkIvarTouchUpInside:(id)sender 
{
    NSLog(@"%s _someArray = %@", __FUNCTION__, _someArray);
}

@end

您可能必须向我们展示您获得 BAD_ACCESS 的示例,因为它必须是其他东西。

在回答“属性”或“ivar”问题时,虽然我对“始终使用属性”的论点表示同情,但我个人将属性用于需要提供外部访问器的任何东西,否则我会使用私有 ivars(不在.h,而是在 .m 文件的私有接口中)。这使得我的 .h 文件中的公共接口在几个月后返回时非常干净且易于理解。如果您确实采用“始终使用属性”的方法,我只建议您对这些属性的公开声明应尽可能限制(如果可以,将属性设为私有,如果不这样做,则将属性的公开声明设为只读) '不需要提供读写访问等)。

顺便说一句,Cocoa 编码指南的命名属性和数据类型是最佳实践的一个很好的参考。

于 2012-07-03T17:44:41.960 回答
0

对于 Obj-C 2.0 及更高版本,似乎没有什么理由使用 iVars。我个人从来没有用过一个。属性只是为您做一切!

于 2012-07-03T16:07:46.590 回答
0

谢谢大家的回复。

如果我调用需要对象的方法(使用 cocos2d 游戏引擎方法):

[self schedule:@selector(someMethod) interval:3.0];

如果我直接调用它而不将它放在 cocos2d 调度程序中,则该对象被取消引用:

[self someMethod];

然后仍然有一个有效的指针。只是为了测试,我保留了它并且它一直存在。

所以现在的问题是我们如何强制保留以防止 ARC 认为我们已经完成并释放它?

将实例变量更改为私有属性可以安全地进行,因此我们将以此作为答案。

于 2012-07-05T16:30:24.987 回答