保留对Objective-C中属性的引用

问题描述 投票:0回答:1

我在课堂上有一个自定义对象属性。我在函数中分配此对象。一旦函数完成,将释放属性。我不希望那样发生。我希望该对象保留到对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. 

objective-c properties automatic-ref-counting
1个回答
0
投票

您的代码中的其他地方还有其他事情,因为上面提供的代码不会释放该MyCustomClass实例。可能导致_obj引用的实例被释放的一些可能情况包括:

  • _obj在其他地方被设置为nil
  • _obj重新设置(例如您再次调用func),旧实例将被释放;或
  • MyClass,父对象本身被释放。

我建议通过两件事来诊断正在发生的事情:

  1. 首先,我建议将dealloc方法同时添加到MyClassMyCustomClass中,以便您看到它们何时被释放:

    - (void)dealloc {
        NSLog(@"%s", __FUNCTION__);
    }
    
  2. 如果您仍然无法推断出正在发生的事情,我建议您使用仪器来跟踪对所涉及对象的所有引用。

    例如,启动分析器(命令 + i或“产品”»“配置文件”),然后选择“泄漏”仪器。开始录制会话之前,请确保将“分配”工具的“录制选项...” 不是设置为“放弃事件以释放已释放的内存”,但将is设置为“记录参考”计数”:

    enter image description here

    您现在可以记录您的分析会话。就个人而言,我添加了“兴趣点”工具,并在创建该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中看到这些路标。

    无论如何,请锻炼您的应用程序,以便您可以发现问题。然后停止录音。然后选择分配工具并找到您的对象:

    enter image description here

    您可以(通过单击该对象的地址旁边的箭头,然后可以查看添加和删除的每个引用:

    enter image description here

不仅我看到它已被释放,而且可以看到发生此事件的完整堆栈跟踪。注意,func方法不在此堆栈跟踪中,而是位于viewDidLoaddealloc内部的MyClass中,这触发了deallocMyCustomClass。我什至可以双击右边堆栈中的viewDidMethod,直接将其移到发生位置:

enter image description here

我现在看到的问题是,我“不小心”将MyClass设置为局部变量。因此,我将其更改为使用该属性(当前已被注释掉),问题将消失。

现在毫无疑问,您所遇到问题的确切来源将有所不同,但是通过明智的dealloc记录,并且借助Instruments的功能,向我们显示已添加和删除的每个参考,您应该能够诊断问题。而且,不要忘了走完整的堆栈跟踪记录(重点放在白色的代码上),看看那里是否所有内容都有意义。通常,我们会停留在有问题的属性上(在您的示例中为obj),而忘记了在堆栈跟踪中更早的内容。

© www.soinside.com 2019 - 2024. All rights reserved.