我有以下协议:
一个从Storyboard实例化ViewController的人:
protocol Storyboarded {
static func instantiate() -> Self
}
extension Storyboarded where Self: UIViewController {
static func instantiate() -> Self {
// this pulls out "MyApp.MyViewController"
let fullName = NSStringFromClass(self)
// this splits by the dot and uses everything after, giving "MyViewController"
let className = fullName.components(separatedBy: ".")[1]
// load our storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// instantiate a view controller with that identifier, and force cast as the type that was requested
return storyboard.instantiateViewController(withIdentifier: className) as! Self
}
}
一个将依赖项注入到Viewcontrollers中的
protocol DependencyInjection where Self: UIViewController {
associatedtype myType: DependencyVC
func injectDependencys(dependency: myType)
}
现在我想添加另一个,所以我可以从依赖关系本身创建ViewController:
protocol DependencyVC {
associatedtype myType: DependencyInjectionVC & Storyboarded
func createVC() -> myType
}
extension DependencyVC {
func makeVC<T: Storyboarded & DependencyInjection>() -> T where T.myType == Self {
let viewController = T.instantiate()
viewController.injectDependencys(dependency: self)
return viewController
}
}
但我自己会遇到此错误:
无法使用类型为参数的列表调用“ injectDependencys” '(依赖:自我)'
这是我拥有的DependencyClass:
class TopFlopDependency: DependencyVC {
typealias myType = TopFlopVC
var topFlopState: TopFlopState
lazy var topFlopConfig: TopFlopConfig = {
let SIBM = StatIntervalBaseModel(stat: "ppc", interval: "24h", base: "usd")
return TopFlopConfig(group: Groups.large, base: "usd", valueOne: SIBM)
}()
init(state: TopFlopState) {
self.topFlopState = state
}
func createVC() -> TopFlopVC {
let topflopVC = TopFlopVC.instantiate()
topflopVC.injectDependencys(dependency: self)
let viewController: TopFlopVC = makeVC()
return topflopVC
}
}
使用makeVC时出现此错误:
'TopFlopDependency'需要类型'TopFlopDependency.myType'和 “ TopFlopDependency.myType”(也称为“ TopFlopVC”)等同于使用 'makeVC'
其他解决方案:
protocol DependencyVC {
}
extension DependencyVC {
func makeVC<T: Storyboarded & DependencyInjection>() -> T where T.myType == Self {
let viewController = T.instantiate()
viewController.injectDependencys(dependency: self)
return viewController
}
}
尝试使用时:
let viewController: TopFlopVC = makeVC()
我收到无法推断T的错误。
为什么我不能这样做?您有解决方案,我将如何使其正常工作?
谢谢!
答案 0 :(得分:1)
调用viewController.injectDependencys(dependency: self)
时,已知self
是DependencyVC
的某种子类型。但是,DependencyInjection
的{{1}}只是说,符合associatedtype myType: DependencyVC
的类型将对DependencyInjection
使用 some 类型(符合{{1 }})。因此,不能保证其实际类型将是myType
的子类型。
DependencyVC
与通用类型参数的工作方式不太相同,因为在“定义”类型时给出myType
,而在“使用”类型时给出通用类型参数。
这全都归结为您可能可能不想拥有associatedtype
,而是直接服用associatedtype
。
鉴于您提供的其他信息,我相信这将是最好的解决方案:
associatedtype myType
您可能会注意到,我将DependencyVC
重命名为protocol DependencyInjection where Self: UIViewController {
func injectDependency(_ dependency: DependencyVC)
}
protocol DependencyVC {
func makeVC<T: Storyboarded & DependencyInjection>() -> T
}
extension DependencyVC {
func makeVC<T: Storyboarded & DependencyInjection>() -> T {
let viewController = T.instantiate()
viewController.injectDependency(self)
return viewController
}
}
是很随意的,因为您只注入了一个依赖项,而injectDependencys(dependency: DependencyVC)
标签并没有真正添加任何内容。呼叫站点。
无论如何,这允许您使用依赖项创建视图控制器的实例。假设您将依赖项存储在名为injectDependency(_ dependency: DependencyVC)
的变量中,然后可以通过转到dependency:
答案 1 :(得分:1)
您需要添加另一个约束。您的DependencyInjection协议需要一种非常特定的DependencyVC(myType)类型。但是您的DependencyVC扩展可与任何DependencyVC一起使用。因此,您需要使用where子句将T的myType约束为相同类型:YouTube
因此,完整的示例如下:
func createVC<T: Storyboarded & DependencyInjection>() -> T where T.myType == Self