Realm单例中泛型闭包返回不同类型数组的实现求助
解决Realm泛型函数根据枚举返回对应类型数组的问题
你的核心需求是让泛型fetchItem函数根据DataType枚举的不同case,向闭包返回对应类型的数组。这里的关键是让枚举和对应的Realm模型类型建立关联,再通过类型转换实现泛型适配。下面分两种场景给出解决方案:
场景1:直接返回Realm对象数组
如果你的需求是直接返回Realm的Object子类数组,可以按以下步骤改造:
1. 重构DataType枚举,关联Realm模型
首先修正枚举命名(case是Swift关键字,需加反引号避免冲突),并添加计算属性关联对应Realm模型类型:
import RealmSwift enum DataType { case `case` case product case category case composition // 关联每个case对应的Realm模型类型 var realmModelType: Object.Type { switch self { case .`case`: return Case.self case .product: return Product.self case .category: return Category.self case .composition: return Composition.self } } }
2. 实现泛型查询函数
给泛型T添加Realm.Object约束,确保传入类型合法,再通过枚举关联的模型类型执行查询:
func fetchItem<T: Object>(type: DataType, complete: @escaping ([T]) -> Void) { do { let realm = try Realm() // 校验泛型类型与枚举关联模型是否匹配 guard let targetType = type.realmModelType as? T.Type else { complete([]) print("类型不匹配,请检查泛型类型与DataType的对应关系") return } // 查询并转换为数组返回 let results = realm.objects(targetType) complete(Array(results)) } catch { // 处理Realm初始化错误,避免try!导致崩溃 print("Realm初始化失败:\(error.localizedDescription)") complete([]) } }
3. 调用示例
调用时明确指定泛型类型(或让Swift自动推断):
// 获取Case类型数组 fetchItem(type: .`case`) { (cases: [Case]) in // 处理返回的Realm Case对象数组 } // 获取Product类型数组 fetchItem(type: .product) { (products: [Product]) in // 处理返回的Realm Product对象数组 }
场景2:返回自定义ViewModel数组
如果需要将Realm对象转换为自定义ViewModel后返回,可以通过协议统一转换逻辑:
1. 定义转换协议
protocol RealmConvertible { associatedtype ViewModel func toViewModel() -> ViewModel }
2. 让Realm模型遵守协议
以Case为例,实现转换方法:
extension Case: RealmConvertible { func toViewModel() -> CaseViewModel { // 根据你的需求映射Realm属性到ViewModel return CaseViewModel(id: self.id, name: self.name) } } // 同理给Product、Category、Composition实现协议
3. 改造查询函数
func fetchItem<T>(type: DataType, complete: @escaping ([T]) -> Void) { do { let realm = try Realm() switch type { case .`case`: let realmObjects = realm.objects(Case.self) let viewModels = realmObjects.map { $0.toViewModel() as! T } complete(viewModels) case .product: let realmObjects = realm.objects(Product.self) let viewModels = realmObjects.map { $0.toViewModel() as! T } complete(viewModels) case .category: let realmObjects = realm.objects(Category.self) let viewModels = realmObjects.map { $0.toViewModel() as! T } complete(viewModels) case .composition: let realmObjects = realm.objects(Composition.self) let viewModels = realmObjects.map { $0.toViewModel() as! T } complete(viewModels) } } catch { print("Realm错误:\(error.localizedDescription)") complete([]) } }
4. 调用示例
fetchItem(type: .`case`) { (viewModels: [CaseViewModel]) in // 处理自定义ViewModel数组 }
注意事项
- 避免
try!:直接使用try!会在Realm初始化失败时崩溃,必须用do-catch处理错误。 - 类型安全:场景1中通过
guard let校验泛型类型与枚举模型的匹配性,避免类型不匹配问题。 - 命名规范:尽量避开Swift关键字,比如将
.Case改为.case(加反引号)或.caseModel,提升代码可读性。
内容的提问来源于stack exchange,提问作者廖豪豪
相关产品推荐
相关产品推荐

