swift - 在协议中使用 self in function
问题描述
我有这个协议:
从 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)
}
现在我想再添加一个,这样我就可以从 Dependency 本身创建 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
}
}
但我自己得到这个错误:
无法使用类型为“(依赖项:Self)”的参数列表调用“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 的错误。
为什么我不能这样做?你有一个解决方案我会如何让它工作?
谢谢!
解决方案
当您调用时viewController.injectDependencys(dependency: self)
,self
已知是 的某个子类型DependencyVC
。但是,DependencyInjection
'associatedtype myType: DependencyVC
只是说符合 的类型DependencyInjection
将使用某种类型 for myType
(符合DependencyVC
)。所以不能保证它的实际类型是myType
.
associatedtype
s 与泛型类型参数的工作方式不太一样,associatedtype
因为在“定义”类型时给出了 s,而在“使用”类型时给出了泛型类型参数。
这一切都归结为这样一个事实,即您可能不想拥有 a associatedtype myType
,而是DependencyVC
直接采用 a 。
更新
根据您提供的其他信息,我相信这将是最好的解决方案:
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:
标签并没有真正在调用站点添加任何内容。
无论如何,这允许您使用您的依赖项创建视图控制器的实例。假设您将依赖项存储在名为 的变量中dependency
,然后您可以通过以下方式从中创建视图控制器let topFlopVC: TopFlopVC = dependency.makeVC()
推荐阅读
- laravel - Laravel 加密器有时不起作用
- regex - 正则表达式不包含“--”
- maven - 如何在 SpringBoot 应用程序测试上下文中使用来自测试 application.yml 的 spring 数据源设置的参数实例化 groovy.sql.Sql?
- c# - 有没有更好的方法来使用依赖注入来实例化接口?
- angular - Angular/Ionic Storage,如何动态存储数据
- javascript - 如何在 Vanilla JS 中使用 AJAX 请求并处理返回请求?
- django - 如何将变量中的数据加载到 django 分页器中?
- rvest - 显示在 chrome 中但不在页面源中
- python - 在python中为数组上的自定义函数加速这个for循环
- amazon-web-services - 无法使用 AWS CodePipeline 构建和部署 Go Lambda - BundleType 必须是 YAML 或 JSON