如何";strongify";Swift 2.0中的可选自用防护装置

如何";strongify";Swift 2.0中的可选自用防护装置,swift,swift2,Swift,Swift2,有一个关于如何弱化/强化自我的问题,答案是肯定的,但我想知道如果让,如何使用“自我”而不让它向右漂移: Welcome to Apple Swift version 2.0 (700.0.59 700.0.72). Type :help for assistance. 2> import Foundation 3> class Foo { 4. func guardOptSelf() -> () throws -> Void { 5.

有一个关于如何
弱化
/
强化
自我的问题,答案是肯定的,但我想知道如果让,如何使用“自我”而不让它向右漂移:

Welcome to Apple Swift version 2.0 (700.0.59 700.0.72). Type :help for assistance.
  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. }
repl.swift:6:19: error: pattern matching in a condition requires the 'case' keyword
            guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
                  ^
                  case
repl.swift:6:23: error: binary operator '~=' cannot be applied to two 'Foo?' operands
            guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
你可以给自己加上阴影;你只需要回勾来表示“你知道你在做什么”。例如:

foo.doSomethingAsyncWithBar(bar) { [weak self] result in
    guard let `self` = self else { return }
    self.receivedResult(result)
}
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. }
或者,在您的示例中:

foo.doSomethingAsyncWithBar(bar) { [weak self] result in
    guard let `self` = self else { return }
    self.receivedResult(result)
}
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. }
Swift 4.2 自Swift 4.2以来,您可以使用以下语法:

{ [weak self] in
    guard let self = self else { return }

    // self is not an optional anymore, it is held strongly
}
有关更多信息,请参见快速发展计划

有时,使用
guard let
以外的其他方法也可能有用(例如,更短或更可读)。另请参见以下部分,仅在少数示例中将
strongSelf
替换为
self

Swift 4.1及更早版本 因为
guard让'self`=self
是一个错误,我会尽量避免它。在您的示例中,您可以使用简单的可选链接:

return { [weak self] in
    self?.doSomethingNonOptionalSelf()         
}
有时您可能需要使用self作为参数。在这种情况下,您可以使用
flatMap
(在可选类型上):

如果您需要做更复杂的事情,您可以使用
if let
构造:

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

    // Do something more complicated using strongSelf
}
guard let
构造:

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

    // Do something more complicated using strongSelf
}
或者您可以创建一个私有方法:

{ [weak self] in
    self?.doSomethingMoreComplicated()
}

...

private func doSomethingMoreComplicated() {
    // Do something more complicated
}

从Swift 4.2开始,您不再需要将self与backticks(编译器错误)或类似
strongSelf
的奇怪变量名一起使用。您可以使用
guard let self=self-else{return}
打开
弱self

class Example {

    var closure: (() -> Void)?

    init() {
        self.closure = { [weak self] in
            guard let self = self else {
                return
            }
            // ...
        }
    }
}

你可以在网站上阅读更多关于它的信息

啊,太好了!不知道backtick语言功能。这似乎也不受编译器对变量隐藏的警告设置的影响,像libextobjc这样的库在@weakify/strongify的实现中必须抑制这些设置。虽然这是可行的,但它并不可靠,因为苹果的Chris Lattner称它是一个
编译器错误
,而且它是一个错误,将来可能会更正:我不确定我是否完全理解这个问题,也不确定你的答案。1) 问题是,如果一个被捕获的
自我
在我们处理完之前就被提前解雇了,我们该怎么办?2) 要做到这一点,我们必须比正常的
[弱自我]
多做一步。我们应该使用强引用来捕获它,即
guard let
3)为了使事情变得美好和平滑,我们使用backticks使
self
变得不包裹,因为使用
weak
self
转换为可选项&我们也可以保留self的相同名称。我被问到这个问题的原因是,我的应用程序崩溃了,因为我太快地释放了一个捕获的自我,而关闭没有完成,所以我的应用程序崩溃了。解决方案是使用一个简单的
guard let u=self-else{print(“self为零,您太快杀死/解除了它,无需再做,但没有崩溃:)”)return}
解决了我的崩溃问题,并对不同的备选方案进行了验证。我们可以添加
guard-let-strongSelf=self-else{return}
。遗憾的是,没有一种更简短的方式来表达这个常见的习语。例如,self.method()
中的
[if self]之类的东西,其中self不是nil时执行闭包。感谢@FerranMaylinch,我已经编辑了答案,将
guard let
也包括在内。一个
Dispatch Queue
闭包是一个非常糟糕的例子,因为它不会导致保留周期。