这是有效的,但由于我们还希望在视图控制器中引用模型加载程序,需要能够指定属性的类型。 T 只在初始化程序的上下文中知道,因此无法定义 T 类型的属性,除非使视图控制器类本身成为泛型。相反,让我们使用类型擦除,能够保存某种 T 的引用,而无需实际使用其类型,这可以通过创建擦除类型的类,例如“包装类”来完成:
classAnyModelLoader<T>:ModelLoading{typealiasCompletionHandler=(Result<T>)->Voidprivatelet loadingClosure:(CompletionHandler)->Voidinit<L:ModelLoading>(loader: L)where L.Model== T {
loadingClosure = loader.load
}funcload(completionHandler:CompletionHandler){loadingClosure(completionHandler)}}
以上这种类型擦除技术,其实在 Swift 标准库中也很常用,例如在 AnySequence 类型中。基本上,将关联值要求的协议包装为泛型类型,然后可以直接使用它而无需使使用它的类也是泛型的。现在可以更新之前的 ViewController,使用 AnyModelloader:
overridefuncviewWillAppear(_ animated:Bool){super.viewWillAppear(animated)
loadModel { result inswitch result {case.success(let model):render(model)case.error(let error):render(error)}}}
与许多其它语言相比,使 Swift 更加安全,更不易出错的原因之一是其先进的(并且在某种程度上是不容忍的)类型系统,这是一种语言功能,有时可能会给人留下深刻的印象,使我们的工作效率提高很多,而有时却令人沮丧。在 Swift 中处理泛型时,可能发生的一种情况,以及通常如何使用基于闭包的类型擦除技术来解决这种情况。假设要编写一个类,可以通过网络加载模型,由于不想为应用程序中的每个模型都复制此类,因此选择使其成为泛型类,如下所示:class ModelLoader<T: Unboxable &am.