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

时间:2018-12-03 11:11:36

标签: swift extension-methods

我有一个需要将组件设置为self的类。该组件要求该类实现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() {
   } 
 }

为什么?

2 个答案:

答案 0 :(得分:1)

不需要类型转换。 MyClass采用MyDelegate时,它的 也是MyDelegate

然后懒惰地初始化该属性,以便完全可以在顶层使用self

private lazy var myComponent = Component(requiresAnObjectofTypeMyDelegate: self) 

答案 1 :(得分:1)

问题是在存储的属性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子类,则会出现编译器错误:

  

使用未解决的标识符“ self”               Component(requiresAnObjectofTypeMyClass:self as!MyClass)

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

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

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

在这里,您也不需要演员。不幸的是,lazy let不允许迅速使用(而且没人知道为什么),所以private(set)接近它的语义。

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