【问题标题】:Calling method using optional chaining on weak variable causes EXC_BAD_ACCESS在弱变量上使用可选链接调用方法会导致 EXC_BAD_ACCESS
【发布时间】:2014-06-11 23:44:22
【问题描述】:

更新:这已在 Xcode 6 beta 6 中修复。

以下代码导致delegate?.thing() 行上的 EXC_BAD_ACCESS:

@class_protocol protocol Fooable {
  func foo()
}

class Bar : Fooable {
  func foo() {
  }
}

weak var delegate: Fooable?

let bar = Bar()
delegate = bar
delegate?.foo()

但在我看来一切都是正确的。为了使变量成为weak,它必须具有可选类型。所以变量delegate 是可选的。弱变量的类型也必须是类类型,所以我将协议设置为类协议。由于我使用可选链接,我希望它要么 1) 是 nil,并且什么都不做,或者 2) 不是 nil,然后调用该方法,这应该会成功。但是,它崩溃了。

可能是可选链接不是原子的并且不保留表达式并且对象在检查nil 和随后的调用之间以某种方式被释放?

有趣的是,如果您消除变量bar 并将其直接赋值为delegate = Bar(),那么崩溃就消失了。这真的很令人困惑,因为将表达式分配给变量然后分配变量并直接分配表达式通常应该表现相同。

【问题讨论】:

  • 如果这是另一个 Swift 错误,这并不奇怪
  • 我玩过它,只有当它既是弱协议类型的 时才会发生这种情况(即将声明更改为 weak var delegate: Bar?var delegate: Fooable?解决这个问题)。绝对看起来像一个错误。
  • 我在 XCode 6.1 上遇到了同样的问题。当我在调试模式下运行它时,它很好。但发生在发布模式。

标签: swift weak-references


【解决方案1】:

我怀疑weak var delegate: Fooable? 不起作用的原因是因为使用可选链接的那行代码正在检查协议一致性。

根据 Apple Swift 编程手册:

“即使你不与 Objective-C 互操作,你也需要标记 如果您希望能够使用带有 @objc 属性的协议 检查协议一致性。”

如果您将@class_protocol 替换为@objc,它应该不会崩溃。同样根据手册,使用@objc 只允许类采用协议(不符合结构或枚举)。

【讨论】:

    【解决方案2】:

    像@PartiallyFinite 一样,我也不得不稍微玩一下代码。 Apple 在 Swift 上的 iBook 对此进行了说明,这可能会有所帮助(使用名为 ExampleProtocol 的协议和符合该协议的 SimpleClass 类): “即使变量protocolValue 的运行时类型为SimpleClass,编译器仍将其视为ExampleProtocol 的给定类型。这意味着除了其协议一致性之外,您不会意外访问该类实现的方法或属性。”

    也就是说,您应该能够在您的委托上调用 foo()(除非在调用它之前它不会消失),但请记住这里的委托被声明为类型Fooable?,不是酒吧,在引擎盖下。这可能是一个错误,但我通过输入:

    weak var delegate: Bar? = bar
    delegate?.foo()
    

    【讨论】:

      猜你喜欢
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 2018-05-17
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      相关资源
      最近更新 更多