swift闭包中的自引用有时返回nil

8qgya5xd  于 2023-06-04  发布在  Swift
关注(0)|答案(3)|浏览(474)

我在swift中访问闭包中的示例方法,在某些情况下,selfreference变成nil,导致我的程序崩溃。我尝试使用[weak self]访问,当selfnil时,无法调用示例方法。

[weak self] () -> () in
xmq68pz9

xmq68pz91#

[weak self]的全部意义在于不创建对self的引用(可能是为了避免循环链接和内存泄漏),以便可以释放它。如果发生这种情况,那么self将是nil
您要么不应该使用[weak self],要么最好准备好处理self已经发布并设置为nil的情况。

guard let strong = self else { return }

举个例子:

import UIKit
import PlaygroundSupport

class Foo {
    let name : String

    init(name:String) {
        self.name = name

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            print(self!.name)
        }
    }
}

Foo(name:"freddie")

PlaygroundPage.current.needsIndefiniteExecution = true

在这种情况下,你会得到一个崩溃,因为self在异步回调之前被释放。
您可以将asyncAfter调用更改为:

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            print(self.name)
        }

将保证self不会被释放,直到回调被执行。
或者你可以使用类似的东西:

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            guard let strong = self else { print("self released") ; return }
            print(strong.name)
        }
nlejzf6q

nlejzf6q2#

我可以通过在创建强示例时创建强示例来解决这个问题,在我的例子中,这个弱变量将nil变为self。谢谢大家为我的问题提供建议。

rbl8hiat

rbl8hiat3#

谜语就在你放置示例的根对象的地方。我也有这样的场景,我在一个函数中创建了我的对象,并在同一个函数下的闭包中使用它。
它看起来像:

class A {
    var myProp = ""
    func nilSelf() {
        closureFunc { [weak self] in
            self?.myProp
        }
    }

    func closureFunc(closure: @escaping () -> Void) {
        //There is some work need to be completed to call the closure
        closure()
    }
}

class B {
    func main() {
        let obj = A()
        //I called the below func too inside another closure
        obj.nilSelf()
    }
}

我在某个地方调用了class Bmain(),在调用闭包的时候,main方法已经完成了它的工作,所以变量obj是无效的。于是问题就出现了。
要解决这个问题,请将行'let obj = A()'移动到类作用域。
我希望这可以帮助你或其他人谁正在寻求解决这个问题。如果我错过了什么,请纠正我。

相关问题