dynamicType + приведение к протоколу приводит к сбою

У меня есть эти классы:

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)

Вызывая dynamicType для экземпляра, хранящегося в переменной класса AppData (sharedData), я должен получить класс, соответствующий AppDataProtocol, верно? Я думаю, проблема в том, что dynamicType на самом деле возвращает тип интерфейса (т. е. «AppDataProtocol»), и я, вероятно, не могу ничего вызывать для этого как такового. Может кто-нибудь сказать мне, почему это не работает?


person the_critic    schedule 27.10.2015    source источник
comment
Я не понимаю, что ты пытаешься сделать. AppData.sharedData не инициализирован и не имеет типа, только протокол, которому вы хотите, чтобы он соответствовал. Сработает ли когда-нибудь остальная часть вашего принудительного подавления...   -  person Grimxn    schedule 27.10.2015
comment
@Grimxn На самом деле он инициализирован ... Посмотрите на строку в моем вопросе, которая говорит AppData.sharedData = CustomAppData()   -  person the_critic    schedule 27.10.2015
comment
Пропустил это. Почему вы инициализируете его вне класса? Поскольку вы это делаете, вы должны неявно развернуть его, что означает, что AppData.sharedData.dynamicType является ImplicitlyUnwrappedOptional<AppDataProtocol>.Type, а не AppDataProtocol.Type, что, вероятно, не то, что вы ожидали...   -  person Grimxn    schedule 27.10.2015
comment
@Grimxn Неважно ... Я делаю это, потому что мне нужно динамически менять источники данных для другого модуля. Я думаю, есть лучшие способы сделать это, но я пока оставлю это. Да, именно, как мне обойти эту проблему?   -  person the_critic    schedule 27.10.2015
comment
Сделайте его необязательным AppDataProtocol?, а не неявно развернутым AppDataProtocol! в классе, тогда вы можете развернуть его следующим образом: let appData = (AppData.sharedData!).dynamicType // "CustomAppData.Type", без необходимости понижать.   -  person Grimxn    schedule 27.10.2015
comment
@Grimxn Большое спасибо! Это сработало! Пожалуйста, напишите ответ, чтобы я мог вознаградить вас.   -  person the_critic    schedule 27.10.2015


Ответы (1)


OP, кажется, хочет иметь переменную класса, которая содержит Type (т.е. фактический класс), который соответствует протоколу, но может быть сам переменной (т.е. содержать разные Type этого протокола в разное время).

Проблема в том, что

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

не будет компилироваться, так как sharedData не инициализирован. Одно из решений для этого состоит в том, чтобы сделать его неявно развернутым, как он сделал в вопросе, полагая, что когда он получит к нему доступ, он будет установлен. Проблема здесь в том, что когда он на самом деле получает доступ к переменной dynamicType, это не то, что он ожидает - это на самом деле ImplicitlyUnwrappedOptional<AppDataProtocol>.Type, а не AppDataProtocol.Type.

Решение состоит в том, чтобы просто объявить static var sharedData : AppDataProtocol? вместо static var sharedData : AppDataProtocol!, а затем развернуть его перед вызовом dynamicType, таким образом:

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

OP - не стесняйтесь редактировать, если мое предположение о ваших намерениях не соответствует цели...

person Grimxn    schedule 27.10.2015
comment
Ты прибил его к голове. Спасибо еще раз! - person the_critic; 27.10.2015