我想为设置页面创建一个通用视图控制器。现在设置来自 JSON,但稍后可能会切换实现,这就是我想要协议的原因。例如,LanguageSetting
协议是空的,但通过使用它,我仍然可以为将来保留类型安全,而不必满足于特定的实现(例如 JSON 解码)。
// Protocols
protocol Query {
associatedtype Result
func handleResult(with data: Data) -> Result
}
protocol Setting {
var name: String { get }
var icon: URL? { get }
}
protocol LanguageSetting: Setting {
}
protocol CountrySetting: Setting {
}
// Implementations
struct LanguageSettingQuery: Query {
func handleResult(with data: Data) -> [LanguageSetting] {
return try! JSONDecoder().decode([JSONLanguageSetting].self, from: data)
}
}
struct CountrySettingQuery: Query {
func handleResult(with data: Data) -> [CountrySetting] {
return try! JSONDecoder().decode([JSONCountrySetting].self, from: data)
}
}
struct JSONLanguageSetting: LanguageSetting, Decodable {
var name: String
var icon: URL?
}
struct JSONCountrySetting: CountrySetting, Decodable {
var name: String
var icon: URL?
}
// A generic settings view controller
class LocaleViewController<LocaleQuery: Query>: UIViewController where
LocaleQuery.Result: Sequence, LocaleQuery.Result.Element: Setting {
private var settingItems = [Setting]()
init(query: LocaleQuery) {
settingItems = query.handleResult(with: Data()) as! [Setting]
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let localeVC = LocaleViewController(query: LanguageSettingQuery())
上面是我创建的一个非常简单的实现Playgrounds
。问题是最后一行:
let localeVC = LocaleViewController(query: LanguageSettingQuery())
抛出错误:
不支持使用 'LanguageSetting' 作为符合协议 'Setting' 的具体类型
关于如何解决这个问题的任何想法?
附带说明:
为什么这里需要向下转换?泛型类型约束不足以确保这一点吗?
settingItems = query.handleResult(with: Data()) as! [Setting]