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),但它本身可能是变量(即在不同时间持有该协议的不同 Type
s)。
问题是
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 - 如果我对您的意图的假设偏离目标,请随时编辑...
我有这些 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),但它本身可能是变量(即在不同时间持有该协议的不同 Type
s)。
问题是
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 - 如果我对您的意图的假设偏离目标,请随时编辑...