我正在使用ARC在Objective-C中开发一个应用程序。
我的简化代码如下所示:
ClassA(.m)
MyCustomClass *obj = [[MyCustomClass alloc] initWithValue1:@"abc" value2:1000];
MyViewController *vc = [[MyViewController alloc] initWithObject:obj];
// "vc" will become the first item of a UITabBarController
MyViewController(.h)
- (id)initWithObject:(MyCustomClass *)obj {
...
localReferenceToOjbect = obj;
...
}
- (void)viewWillAppear:(BOOL)animated {
// do something with "localRefernceToObject" <---
}
启动应用程序将导致对僵尸的调用:当显示ViewController时,“obj”将被解除分配,因此我不能再使用它了。
我的解决方法是:
ClassA(.h)
@interface ClassA : UIViewController {
MyCustomClass *obj;
}
ClassA(.m)
obj = [[MyCustomClass alloc] initWithValue1:@"abc" value2:1000];
MyViewController *vc = [[MyViewController alloc] initWithObject:obj];
// "vc" will become the first item of a UITabBarController
这是正确的方法吗?!我不这么认为:为什么我要存储一个对 ClassA 无用的物体的距离?
我无法解释实际发生的事情。你能救我吗?
答案 0 :(得分:1)
你是对的,因为在ClassA中保留对obj的引用是不合逻辑的。
但是如果你需要保持对obj的引用以便MyViewController使用它,请将它保留在MyViewController中,而不是保存在ClassA中,因为那是将使用它的MyViewController。
最简单的方法是将您在localReferenceToObject
中使用的MyViewController
转换为@property(retain) propertyToObject;
(如果您使用ARC,则转换为@property(strong) propertyToObject
)并在您的MyViewController.m
self.propertyToObject
{而不是localReferenceToObject
,以确保调用属性的setter,从而真正保留对象。)
这样,当MyViewController
实例仍然存活时,对象将被保留并保留。
[EDIT] 如果您希望此属性为私有,则可以在类扩展中声明它,以便无法从其他类访问它,如下例所示。有关详细信息,请参阅here in Apple's documentation。
@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
@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中的public还是.m中的private。
如果您使用ARC,您仍然可以使用实例变量而不是属性,因为ARC会为您保留它,但只要您确保您的实例变量声明为strong
而不是weak
。