【问题标题】:dynamicType + cast to protocol leads to crashdynamicType + 强制转换为协议导致崩溃
【发布时间】:2016-01-27 04:46:58
【问题描述】:

我有这些课程:

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 [符合 AppDataProtocol 的类]

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

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

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) 的类变量中的实例调用 dynamicType,我应该得到符合 AppDataProtocol 的类,对吧?我认为问题在于 dynamicType 实际上返回了接口类型(即“AppDataProtocol”),而我本身可能无法调用任何东西。有人能告诉我为什么这不起作用吗?

【问题讨论】:

  • 我不明白你在做什么。 AppData.sharedData 未初始化,也没有类型,只有您希望它遵守的协议。其余的强迫沮丧是否会起作用是没有实际意义的......
  • @Grimxn 它实际上已被初始化......看看我的问题中写着AppData.sharedData = CustomAppData()的行
  • 错过了。你为什么在课外初始化它?既然你这样做了,你必须隐含地解开它,这意味着 AppData.sharedData.dynamicTypeImplicitlyUnwrappedOptional<AppDataProtocol>.Type 而不是 AppDataProtocol.Type 这可能不是你所期望的......
  • @Grimxn 没关系...我这样做是因为我需要为不同的模块动态交换数据源。我想有更好的方法可以做到这一点,但我暂时保留它。是的,确切地说,我该如何解决这个问题?
  • 使其成为可选的AppDataProtocol?,而不是在类中隐式解包AppDataProtocol!,然后您可以这样解包:let appData = (AppData.sharedData!).dynamicType // "CustomAppData.Type",无需向下转换。

标签: swift dynamictype


【解决方案1】:

OP 似乎希望有一个类变量来保存符合协议的Type(即实际类),但它本身可能是变量(即以不同的方式保存该协议的不同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 - 如果我对您的意图的假设偏离目标,请随时编辑...

【讨论】:

  • 你把它钉在了头上。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-29
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多