我在课堂上有一个自定义对象属性。我在函数中分配此对象。一旦函数完成,将释放属性。我不希望那样发生。我希望该对象保留到对MyClass
的引用被激活为止。这是ARC。
这是代码
@interface MyClass : NSObject
@property (nonatomic, strong) MyCustomClass *obj;
@end
@implementation MyClass
- (id)init {
// initialize
_obj = nil;
}
- (void)func {
_obj = [[MyCustomClass alloc] initWithParams...];
// do more things
}
// the object deallocates once the function exits.
您的代码中的其他地方还有其他事情,因为上面提供的代码不会释放该MyCustomClass
实例。可能导致_obj
引用的实例被释放的一些可能情况包括:
_obj
在其他地方被设置为nil
;_obj
重新设置(例如您再次调用func
),旧实例将被释放;或MyClass
,父对象本身被释放。我建议通过两件事来诊断正在发生的事情:
首先,我建议将dealloc
方法同时添加到MyClass
和MyCustomClass
中,以便您看到它们何时被释放:
- (void)dealloc {
NSLog(@"%s", __FUNCTION__);
}
如果您仍然无法推断出正在发生的事情,我建议您使用仪器来跟踪对所涉及对象的所有引用。
例如,启动分析器(命令 + i或“产品”»“配置文件”),然后选择“泄漏”仪器。开始录制会话之前,请确保将“分配”工具的“录制选项...” 不是设置为“放弃事件以释放已释放的内存”,但将is设置为“记录参考”计数”:
您现在可以记录您的分析会话。就个人而言,我添加了“兴趣点”工具,并在创建该MyClass
实例的地方添加了路标,
- (void)viewDidLoad {
[super viewDidLoad];
os_log_t log = os_log_create("ViewController", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
os_signpost_id_t identifier = os_signpost_id_generate(log);
os_signpost_event_emit(log, identifier, "MyClass");
MyClass *myClass = [[MyClass alloc] init]; // the problem here is that I’m using a local variable for the parent class, but the situation in your case may vary
[myClass func];
}
但是如果您知道何时创建该对象,则可能不需要这样做。但是很高兴在Instruments中看到这些路标。
无论如何,请锻炼您的应用程序,以便您可以发现问题。然后停止录音。然后选择分配工具并找到您的对象:
您可以(通过单击该对象的地址旁边的箭头,然后可以查看添加和删除的每个引用:
不仅我看到它已被释放,而且可以看到发生此事件的完整堆栈跟踪。注意,func
方法不在此堆栈跟踪中,而是位于viewDidLoad
的dealloc
内部的MyClass
中,这触发了dealloc
的MyCustomClass
。我什至可以双击右边堆栈中的viewDidMethod
,直接将其移到发生位置:
我现在看到的问题是,我“不小心”将MyClass
设置为局部变量。因此,我将其更改为使用该属性(当前已被注释掉),问题将消失。
现在毫无疑问,您所遇到问题的确切来源将有所不同,但是通过明智的dealloc
记录,并且借助Instruments的功能,向我们显示已添加和删除的每个参考,您应该能够诊断问题。而且,不要忘了走完整的堆栈跟踪记录(重点放在白色的代码上),看看那里是否所有内容都有意义。通常,我们会停留在有问题的属性上(在您的示例中为obj
),而忘记了在堆栈跟踪中更早的内容。