dynamicType + cast to protocol 导致崩溃

dynamicType + cast to protocol leads to crash

我有这些 classes:

AppDataProtocol.swift

public protocol AppDataProtocol{

    var logoImagePath : String! {get}
    var logoTitle : String? {get}
    var logoSubtitle : String? {get}

    var categories : [MainMenuOption]! {get}

    static func contentElements(filter: ContentFilter?) -> [ContentElement]!
}

AppData.swift

class AppData{

   static var sharedData : AppDataProtocol!

   init(){}

}

CustomAppData.swift [Class 符合AppDataProtocol]

class CustomAppData: AppData, AppDataProtocol {
// fulfills the AppDataProtocol, omitted for brevity
}

所以有了这些 classes,我尝试像这样动态设置 class 变量:

AppData.sharedData = CustomAppData()

并像这样访问它:

// we need the class so we can call the class function
let appData = AppData.sharedData.dynamicType as! AppDataProtocol.Type 
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
                             /*CRASH!*/
let contentElements = appData.contentElements(nil)

通过对存储在 AppData (sharedData) class 变量中的实例调用 dynamicType,我应该得到符合 AppDataProtocol 的 class,对吗?我认为问题是 dynamicType 实际上 returns 接口类型(即 "AppDataProtocol"),我可能无法调用它本身的任何东西。有人可以告诉我为什么这不起作用吗?

OP 似乎希望有一个 class 变量,其中包含符合协议的 Type(即实际的 class),但它本身可能是变量(即在不同时间持有该协议的不同 Types)。

问题是

class AppData{
   static var sharedData : AppDataProtocol
   init(){}
}

将无法编译,因为 sharedData 未初始化。一个解决方法是让它隐式解包,就像他在问题中所做的那样,相信当他访问它时它 will 已经设置。这样做的问题是,当他实际访问变量的 dynamicType 时,这不是他所期望的 - 它实际上是 ImplicitlyUnwrappedOptional<AppDataProtocol>.Type 而不是 AppDataProtocol.Type.

解决方案是简单地声明 static var sharedData : AppDataProtocol? 而不是 static var sharedData : AppDataProtocol!,然后在调用 dynamicType 之前解包,因此:

let appData = (AppData.sharedData!).dynamicType // "CustomAppData.Type"

OP - 如果我对您的意图的假设偏离目标,请随时编辑...