3

我正在使用 ARC 在 Objective-C 中开发一个应用程序。

我的简化代码如下所示:

A 类 (.m)

MyCustomClass *obj = [[MyCustomClass alloc] initWithValue1:@"abc" value2:1000];
MyViewController *vc = [[MyViewController alloc] initWithObject:obj];
// "vc" will become the first item of a UITabBarController

我的视图控制器 (.h)

- (id)initWithObject:(MyCustomClass *)obj {
    ...
    localReferenceToOjbect = obj;
    ...
}

- (void)viewWillAppear:(BOOL)animated {
    // do something with "localRefernceToObject" <---
}

启动应用程序将导致对僵尸的调用:当显示 ViewController 时,“obj”将已被释放,因此我不能再使用它了。

我的解决方法是:

A 类 (.h)

@interface ClassA : UIViewController {
    MyCustomClass *obj;
}

A 类 (.m)

obj = [[MyCustomClass alloc] initWithValue1:@"abc" value2:1000];
MyViewController *vc = [[MyViewController alloc] initWithObject:obj];
// "vc" will become the first item of a UITabBarController

这是正确的方法吗?!我不这么认为:为什么我要存储一个对ClassA无用的对象的 istance ?
我无法解释实际发生的事情。你可以帮帮我吗?

4

1 回答 1

1

你是对的,在 ClassA 中保留对 obj 的引用是不合逻辑的。

但是,如果您需要保留对 obj 的引用以供 MyViewController 使用它,请将其保留在 MyViewController 中,而不是 ClassA 中,因为将使用它的是 MyViewController。

最简单的方法是将localReferenceToObject您使用的 inMyViewController转换为@property(retain) propertyToObject;(或者@property(strong) propertyToObject如果您使用 ARC)并在您的MyViewController.mwith中访问它self.propertyToObject(而不是localReferenceToObject,以确保调用属性的设置器,从而真正保留对象)。

这样,当您的MyViewController实例仍然存在时,该对象将被保留并保留。


[编辑]如果您希望此属性是私有的,您可以在类扩展中声明它,以便其他类无法访问它,如下例所示。有关更多详细信息,请参阅Apple 文档中的此处。

在您的 MyViewController.h 头文件中

@interface MyViewController : UIViewController
// Here you write the public API in the .h / public header
// If you don't want your property to be visible, don't declare it there
@end

在您的 MyViewController.m 文件中

@interface MyViewController ()
// This is the private API, only visible inside the MyViewController.m file and not from other classes
// Note the "()" to declare the class extension, as explained in Apple doc
@property(nonatomic, retain) MyCustomClass* referenceToObject; // Note: use strong (which is a synonym of retain) if you use ARC
@end

@implementation MyViewController
@synthesize referenceToObject = _referenceToObject; // not even needed with modern ObjC and latest LLVM compiler

- (id)initWithObject:(MyCustomClass *)obj
{
    self = [super init];
    if (self) {
        ...
        self.referenceToOjbect = obj;
        ...
    }
    return self;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // do something with "self.refernceToObject"
}

// This memory management code is only needed if you don't use ARC
-(void)dealloc
{
    self.referenceToObject = nil; // release memory
    [super dealloc];
}

就个人而言,正如 Apple 在一些 WWDC 会议中所建议的那样,我现在真的很少使用实例变量,而是更喜欢使用属性,无论是 .h 中的公共还是 .m 中的私有。


如果您使用 ARC,您仍然可以使用实例变量而不是属性,因为 ARC 会为您保留它,但只要您确保您的实例变量声明为strong而不是weak.

于 2012-10-18T09:19:08.503 回答