How to “strongify” optional self using guard in Swift 2.0

后端 未结 3 1026
攒了一身酷
攒了一身酷 2020-12-08 09:52

There\'s a similar question about how to weakify/strongify self, which is answered, but I\'m wondering how to use \"self\" without rightward-drifti

相关标签:
3条回答
  • 2020-12-08 10:26

    As of Swift 4.2 you no longer need to use self with backticks (compiler bug) or weird variable names like strongSelf. You can use guard let self = self else { return } to unwrap weak self:

    class Example {
    
        var closure: (() -> Void)?
    
        init() {
            self.closure = { [weak self] in
                guard let self = self else {
                    return
                }
                // ...
            }
        }
    }
    

    You can read more about it in the Swift evolution proposal.

    0 讨论(0)
  • 2020-12-08 10:28

    You can shadow self; you just need backticks to indicate that "you know what you're doing". For example:

    foo.doSomethingAsyncWithBar(bar) { [weak self] result in
        guard let `self` = self else { return }
        self.receivedResult(result)
    }
    

    Or, in your example:

    2> import Foundation
    3> class Foo {
    4.     func guardOptSelf() -> () throws -> Void {
    5.         return { [weak self] in
    6.             guard let `self` = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
    7.             self.doSomethingNonOptionalSelf()         
    8.         }
    9.     }
    10. }
    
    0 讨论(0)
  • 2020-12-08 10:33

    Swift 4.2

    Since Swift 4.2 you can use the following syntax:

    { [weak self] in
        guard let self = self else { return }
    
        // self is not an optional anymore, it is held strongly
    }
    

    For more see the Swift evolution proposal SE-0079.

    Sometimes other approaches than using guard let might be useful as well (e.g. shorter or more readable). See also the following section, just replace strongSelf with self in few examples.

    Swift 4.1 and earlier

    Because guard let `self` = self is a compiler bug as stated by Chris Lattner I would try to avoid it. In your example you can use just simple optional chaining:

    return { [weak self] in
        self?.doSomethingNonOptionalSelf()         
    }
    

    Sometimes you might need to use self as a parameter. In such case you can use flatMap (on an optional type):

    { [weak self] in
        self.flatMap { $0.delegate?.tableView($0, didSelectRowAt: indexPath) }
    }
    

    In case you need to do something more complicated you can use if let construct:

    { [weak self] in
        if let strongSelf = self {
            // Do something more complicated using strongSelf
        }
    }
    

    or guard let construct:

    { [weak self] in
        guard let strongSelf = self else { return }
    
        // Do something more complicated using strongSelf
    }
    

    or you can create a private method:

    { [weak self] in
        self?.doSomethingMoreComplicated()
    }
    
    ...
    
    private func doSomethingMoreComplicated() {
        // Do something more complicated
    }
    
    0 讨论(0)
提交回复
热议问题