【问题标题】:Can an object be deallocated during method execution?可以在方法执行期间释放对象吗?
【发布时间】:2021-04-22 15:15:31
【问题描述】:

假设我们在主线程上创建了一个类var foo: Foo? = Foo()的实例,并在另一个线程上调用Foo的一些耗时的实例方法bar,不久之后我们将foo设置为@987654326 @ 在主线程上。 bar 的执行会发生什么,据我了解,bar 仍应继续执行,因为调用实例方法隐式将 self 作为第一个参数传递,所以即使是对 foo 的最后一个显式引用也被破坏了,我们仍然在方法中有一个 ref,它应该很好。但后来我发现了这个stackoverflow post,这完全打破了我的理解。那么,有人可以确认/否认对象在其方法执行期间无法释放的事实吗

【问题讨论】:

    标签: ios swift automatic-ref-counting


    【解决方案1】:

    简短的回答是您的信念是正确的,并且您正在研究一个与 Swift 无关的问题。

    您的链接指向非 ARC Objective-C。 Swift 总是使用 ARC,而 ARC 对保留非常保守。考虑以下 Objective-C 调用:

    [target runMethod: parameter];
    

    在 ARC 下,这(在概念上)转换为:

    [target retain];
    [parameter retain];
    [target runMethod: parameter];
    [parameter release];
    [target release];
    

    retainrelease 是原子的、线程安全的调用。

    在 Swift 中也存在类似的行为。正因为如此,作为一般规则(在没有 Unsafe 的情况下),一个变量不会在你持有它时“消失”。

    这是实现细节。更好的考虑方法是默认变量和参数是强的,当有强引用时对象不能被销毁。这符合你的理解。

    不过,在 ARC 之前,您需要自己插入额外的保留和释放以防止出现这种情况,而且通常不这样做。 (在 10.6 之前,大多数 ObjC 都是单线程的。)

    即使没有线程,也有可能在没有 ARC 的情况下误入歧途。由于调用者通常不会立即保留返回值,如果他们只是暂时需要它们,即使没有多个线程也有可能获得悬空指针。例如,对于没有内存管理的普通访问器,这可能会崩溃:

    NSString *name = [person name];
    [person release];
    [self doSomethingWithName: name];
    

    这就是为什么你经常看到旧的 ObjC getter 写成以下形式:

    - (NSString*) title {
        return [[title retain] autorelease];
    }
    

    即使self 释放它或self 被释放,返回的值也会一直存在到事件循环结束。

    Swift 通过 ARC 做类似的事情,但顾名思义,这都是自动的。

    【讨论】:

    • 谢谢你这么棒的回答,接受了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多