无法将 MyClass 类型的值转换为 MyDelegate

Cannot cast value of type MyClass to MyDelegate

我有一个 class 需要将组件设置为 self。该组件需要 class 来实现 protocol MyDelegate。最终,它失败了 (SIGNAL SIGABRT)。

// I need the class to be a NSObject for unrelated requirements 
class MyClass: NSObject {

// I force the compilation, but it then breaks apart at runtime anyway
 private let myComponent = 
 Component(requiresAnObjectofTypeMyDelegate: self as! MyDelegate) 
}

// in the same file 
 extension MyClass: MyDelegate {  
   func myUsefulDelegateCall() {
   } 
 }

为什么?

不需要类型转换。由于 MyClass 采用 MyDelegate 也是 MyDelegate.

并延迟初始化 属性 以便能够在顶层使用 self

private lazy var myComponent = Component(requiresAnObjectofTypeMyDelegate: self) 

问题是 self 在存储的 属性 myComponent 中的用法。 通常,在初始化程序完成整个对象的初始化之前,不允许分发 self。因此,您的问题与协议或扩展无关。更简单:

import Foundation


class Component {
    init(requiresAnObjectofTypeMyClass:MyClass) {
    }
}

// I need the class to be a NSObject for unrelated requirements 
class MyClass : NSObject {

    // I force the compilation, but it then breaks apart at runtime anyway
    private let  myComponent = 
        Component(requiresAnObjectofTypeMyClass : self as! MyClass)
}

let m = MyClass()

也会崩溃。

如果省略 NSObject 子类化,则会出现编译器错误:

use of unresolved identifier 'self' Component(requiresAnObjectofTypeMyClass : self as! MyClass)

这表明问题所在:您不能在此处使用 self。 我认为这只是一个 Xcode 错误; Xcode 似乎忽略了继承 NSObject 时的语法错误。强制转换 as! MyClass 也暗示我们正在寻找一种奇怪的解决方法,最终 Xcode 屈服并导致运行时崩溃。

要解决这个问题,您可以创建一个惰性 属性,它将在初始化过程之后进行评估,因此将允许 self 被传递给 Component 初始化程序:

private(set) lazy var  myComponent = Component(requiresAnObjectofTypeMyClass:self)

在这里,你也不需要强制转换。不幸的是,swift 中不允许 lazy let(没人知道为什么),所以 private(set) 接近它的语义。

将此代码转移到您的协议示例中很容易。