Objective-C ARC and Instance Variables iOS SDK



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

@interface SomethingElse : Something  {
    NSMutableArray *someArray;
}

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

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

我们

是否应该转换我们想要的所有局部变量 保留到私人财产还是我错过了一些明显的东西?

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

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

@property 与

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

ARC的retain版本称为strong

基本上,您将使用以下内容声明它:

@property (strong) NSMutableArray *someArray;

有关详细信息,请参阅"强"关键字的作用。

通常

最好使用属性而不是局部变量,因为这些属性可以"免费"获得访问器/资源库,并且通常更易于使用。

您在其他一些评论中描述了一个BAD_ACCESS问题。这里还有其他事情发生。在 ARC 中,除非另有资格,否则您的 ivar 很强(在非 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"问题时,

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

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

对于 Obj-C 2.0 及更高版本,似乎没有理由使用 iVars。我个人永远没有使用过。物业只是为你做一切!

感谢大家的回复。

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

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

如果我直接调用它而不将其放入 cocos2d 调度器,则该对象被取消引用:

[self someMethod];

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

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

将实例变量更改为私有属性可以安全地做到这一点,因此我们将以此作为答案。

最新更新