我有一个需要将组件设置为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() {
}
}
为什么?
答案 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)
接近它的语义。
很容易将此代码转移到您的协议示例中。