ChatGPT解决这个技术问题 Extra ChatGPT

使用 ARC 时是否在 dealloc 中将属性设置为 nil?

我正在尝试学习 iOS 5 中的自动引用计数。现在这个问题的第一部分应该很简单:

使用 ARC 时我不需要在我的 dealloc 中编写显式释放属性语句是否正确?换句话说,以下是否确实不需要显式的dealloc? @interface MyClass : NSObject @property (strong, nonatomic) NSObject* myProperty; @end @implementation MyClass @synthesize myProperty; @end 我的下一个更重要的问题来自 Transitioning to ARC Release Notes 文档中的一行:您不必(实际上不能)释放实例变量,但您可能需要在系统类上调用 [self setDelegate:nil] 和其他未使用 ARC 编译的代码。这就引出了一个问题:我怎么知道哪些系统类不是用 ARC 编译的?我什么时候应该创建自己的 dealloc 并将强保留属性显式设置为 nil?我是否应该假设属性中使用的所有 NS 和 UI 框架类都需要显式释放?

在 SO 和其他地方有大量关于在使用手动引用跟踪时释放属性的支持 ivar 的做法的信息,但在使用 ARC 时,这方面的信息相对较少。


L
Lily Ballard

简短回答:不,您不必在 ARC 下清除 dealloc 中的属性。

长答案:您不应该在 dealloc 中清空属性,即使在手动内存管理中也是如此。

在 MRR 中,你应该释放你的 ivars。取消属性意味着调用 setter,这可能会调用它不应该在 dealloc 中触及的代码(例如,如果您的类或子类覆盖了 setter)。同样,它可能会触发 KVO 通知。相反,释放 ivar 可以避免这些不良行为。

在 ARC 中,系统会自动为您释放任何 ivars,因此如果您只这样做,您甚至不必实现 dealloc。但是,如果您有任何需要特殊处理的非对象 ivars(例如,您需要 free() 分配的缓冲区),您仍然必须处理 dealloc 中的那些。

此外,如果您已将自己设置为任何对象的委托,则应在 dealloc 中取消设置该关系(这是关于调用 [obj setDelegate:nil] 的部分)。关于在未使用 ARC 编译的类上执行此操作的说明是对弱属性的一种认可。如果该类将其 delegate 属性显式标记为 weak,那么您不必这样做,因为弱属性的性质意味着它将为您取消。但是,如果该属性被标记为 assign,那么您应该在您的 dealloc 中将其 nil,否则该类将留下一个悬空指针,并且如果它尝试向其委托发送消息,则可能会崩溃。请注意,这仅适用于非保留关系,例如委托。


这是有道理的!不过让我问你这个问题:我遇到的一个常见情况是我有一个 MyController : UIViewController 类,它创建并拥有一个 UIView 并将视图的委托设置为自身。它是该视图的唯一保留所有者。当控制器被解除分配时,视图也应该被解除分配。那么委托指针是否悬空是否重要?
@emfurry:可能不会,因为当您的视图控制器死亡时,视图本身不应该在视图层次结构中并且不应该做任何事情,但最好不要做出假设。如果视图异步安排了稍后完成的工作,并且视图本身最终比它的视图控制器寿命短了一段时间(例如,由于异步工作暂时保留了视图)怎么办?为了安全起见,最好只取消代表。事实上,如果有问题的视图是 UIWebView,文档明确声明您需要取消委托。
@zeiteisen:不。 unsafe_unretained 完全等同于 assign 属性,并且是 MRR 下委托关系的正常行为,这些需要被取消。
我不同意在与 MRC 的 dealloc 中不使用 setter 的说法。苹果不推荐它,但他们也在他们的代码中这样做。您实际上可以通过不使用设置器来创建新问题。有几个关于它的大讨论。重要的是正确地编写 setter(如果你传递一个 nil 值,它必须正确运行),有时还要注意释放的顺序。
@Sulthan:是否在 dealloc 中使用 setter 是一大堆蠕虫,但我的立场基本上可以归结为:您想在 dealloc 中调用尽可能少的代码。 Setter 倾向于包含副作用,或者通过在子类中覆盖,或者通过 KVO,或其他机制。像瘟疫一样,应该特别避免 dealloc 中的副作用。如果您可以从 dealloc 中删除方法调用,则应该这样做。这被简化为:不要在 dealloc 中调用 setter。
C
Cœur

只是给出相反的答案......

简短回答:不,您不必在 ARC 下的 dealloc 中清除自动合成的属性。而且您不必为 init 中的那些使用设置器。

长答案:您应该dealloc 中消除自定义综合属性,即使在 ARC 下也是如此。您应该为 init 中的设置使用设置器。

关键是您的自定义合成属性在无效化方面应该是安全和对称的。

一个可能的定时器设置器:

-(void)setTimer:(NSTimer *)timer
{
    if (timer == _timer)
        return;

    [timer retain];
    [_timer invalidate];
    [_timer release];
    _timer = timer;
    [_timer fire];
}

scrollview、tableview、webview、textfield 的可能设置器,...:

-(void)setScrollView:(UIScrollView *)scrollView
{
    if (scrollView == _scrollView)
        return;

    [scrollView retain];
    [_scrollView setDelegate:nil];
    [_scrollView release];
    _scrollView = scrollView;
    [_scrollView setDelegate:self];
}

KVO 属性的可能设置器:

-(void)setButton:(UIButton *)button
{
    if (button == _button)
        return;

    [button retain];
    [_button removeObserver:self forKeyPath:@"tintColor"];
    [_button release];
    _button = button;
    [_button addObserver:self forKeyPath:@"tintColor" options:(NSKeyValueObservingOptions)0 context:NULL];
}

这样您就不必为 deallocdidReceiveMemoryWarningviewDidUnload... 复制任何代码,并且您的财产可以安全地公开。如果您担心 dealloc 中的 nil out 属性,那么可能是时候再次检查您的设置器了。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅