swift 迅速,摆脱封闭,保留自我,打开自我是否有益?

pxy2qtax  于 2022-12-10  发布在  Swift
关注(0)|答案(2)|浏览(122)

I've been wondering if unwrapping weak self within the escaping closure's scope brings some benefits other than aesthetical ones? Consider those two examples:
When we unwrap self:

func test() {
        Test.closureFunction { [weak self] parameter in
            guard let self = self else { return }
            self.someFunction(parameter)
        }
    }

When we don't unwrap self:

func test() {
        Test.closureFunction { [weak self] parameter in
            self?.someFunction(parameter)
        }
    }

Could there be a scenario when not unwrapped self (1st example) may become nil as a result of some other asynchronous operation, thus the execution of the scope may differ from when we unwrap self (2nd example)? I believe it's a possible scenario, but I may be wrong.
I think that we may still want to execute an operation from within the escaping closure's scope while self is already nil. After this escaping closure finishes its scope the unwrapped self is released.
Thank you

zwghvu4y

zwghvu4y1#

The answer is "it depends."
If you use a guard let , your closure captures self at the beginning of the closure. Self will not get released until your closure has finished running. Also, you won't need to unwrap it each time you use it (The "aesthetic" part)
In most cases, this makes sense, since once you start doing work in your closure, you likely want to do all that work.
If you don't use a guard let , your instance of self could get released in the middle of your closure's execution.
If the owner of your object (whoever is keeping a strong reference to self) might release the object while your closure is running and that means there is no point in continuing (which will depend on your use-case) then don't use a guard let and instead keep unwrapping, and/or keep checking to see if self is nil, and returning if it is nil.

zwghvu4y

zwghvu4y2#

邓肯C很好地解释了这些问题,但我认为一个简单的例子就能说明问题:

// In this version, `someFunction` and `otherFunction` will either both execute
// or both will not execute. That is typically what you'd want.
Test.closureFunction { [weak self] parameter in
    guard let self = self else { return }
    self.someFunction(parameter)
    self.otherFunction(parameter)
}

// In this version, it is possible for `someFunction` to execute, but 
// `otherFunction` not to execute. That can be fine, but it's a little weird
// and harder to reason about. I wouldn't generally do this.
// But also, it's rarely going to be a real problem.
Test.closureFunction { [weak self] parameter in
    self?.someFunction(parameter)
    self?.otherFunction(parameter)
}

关键的一点是,在这两种情况下,代码都是“安全的”。(在没有未定义的行为/不安全的代码或Swift bug的情况下)self不可能是一个悬空指针,也不可能改变它所指向的对象。

相关问题