SwiftUI泛型视图中如何正确表达FavouritesArray参数的关联关系?
泛型SwiftUI视图适配FavouritesArray协议解决方案
问题背景
先定义了以下协议:
protocol ListableArrayElement: Identifiable, Equatable { associatedtype T = Hashable var id:T { get } } protocol Listable: ObservableObject, RandomAccessCollection where Element == ArrayElement { associatedtype ArrayElement: ListableArrayElement var _elements: [ArrayElement] { get set } var count: Int { get } var isEmpty: Bool { get } var endIndex: Int { get } var startIndex: Int { get } subscript(position: Int) -> ArrayElement { get set } func index(after i: Int) -> Int func append(_ element: ArrayElement) func insert(_ newElement: ArrayElement, at i: Int) func remove(at index: Int) func removeAll() func index(of element: ArrayElement) -> Int? } protocol FavouritesArray: Listable, Codable where Element: Codable { // MARK: - PROPERTIES var _elements: [Element] { get set } var key: String { get set } init() init(key: String) }
FavouritesArray通过关联扩展实现了元素增删、基于key持久化到UserDefaults的功能,Listable协议用于避免核心为元素数组的ViewModel重复编写代码。
现在需要编写泛型SwiftUI视图,通过EnvironmentObject传递遵循FavouritesArray的实例,但编写类型签名时遇到编译错误:
尝试的代码:
struct FavouritesArrayView<Favourites: FavouritesArray, Favourite>: View where Favourite == FavouritesArray.Element { @EnvironmentObject var favourites: Favourites @ObservedObject var favourite: Favourite // Other properties here var body: some View { // Layout code here } }
触发错误:Associated type 'Element' can only be used with a concrete type or generic parameter base
解决方案
错误原因是FavouritesArray.Element是协议的关联类型,不能直接在泛型约束中使用,应该绑定到泛型参数Favourites的关联类型Element。有两种修正方式:
方式一:使用typealias简化类型声明
struct FavouritesArrayView<Favourites: FavouritesArray>: View { // 直接关联到泛型参数的Element类型 typealias Favourite = Favourites.Element @EnvironmentObject var favourites: Favourites @ObservedObject var favourite: Favourite // Other properties here var body: some View { // Layout code here } }
方式二:显式在泛型约束中关联
struct FavouritesArrayView<Favourites: FavouritesArray, Favourite>: View // 约束Favourite等于具体泛型参数Favourites的Element类型 where Favourite == Favourites.Element { @EnvironmentObject var favourites: Favourites @ObservedObject var favourite: Favourite // Other properties here var body: some View { // Layout code here } }
关键注意点
- 核心修改是将约束中的
FavouritesArray.Element替换为Favourites.Element,因为Favourites是遵循协议的具体泛型参数,它的Element关联类型是明确可推导的。 - 如果使用
@ObservedObject修饰favourite,需要确保Favourites.Element遵循ObservableObject协议;若元素只是纯数据模型,可改用@State或@Binding管理状态。
内容的提问来源于stack exchange,提问作者Philip Pegden
相关产品推荐
相关产品推荐

