ios - 以 "generic"方式将 NSManagedObject 转换为结构体 (Swift)

标签 ios swift generics

我有一个 CoreDataStore 类,它有两个通用占位符,可用于模型中的每个实体类型。这个想法是它从存储中获取一个 NSManagedObject 子类(基于一种泛型类型),将其转换为适当的对象(基于另一种泛型类型)并返回该对象。

此行为的目的是为了保持核心数据方面的封装并避免在整个应用程序中传递 NSManagedObject 实例。

潜在用途示例

这纯粹是用法可能看起来如何进一步证明我正在努力实现的目标。

let personStore = CoreDataStore<ManagedPerson, Person>()
let personData = personStore.fetchSomeObject() // personData is a value type Person

我有以下代码,分为多个文件,但为简单起见,此处以修改后的方式显示。

import Foundation
import CoreData

// MARK: - Core Data protocol and managed object

protocol ManagedObjectProtocol { }

class ManagedPerson: NSManagedObject, ManagedObjectProtocol {
    var title: String?
}

class ManagedDepartment: NSManagedObject, ManagedObjectProtocol {
    var name: String?
}

// MARK: - Simple struct representations

protocol DataProtocol {
    typealias ManagedObjectType: ManagedObjectProtocol
    init(managedObject: ManagedObjectType)
}

struct Person {
    var title: String?
}

struct Department {
    var name: String?
}

extension Person: DataProtocol {
    typealias ManagedObjectType = ManagedPerson
    init(managedObject: ManagedPerson) {
        self.title = managedObject.title
    }
}

extension Department: DataProtocol {
    typealias ManagedObjectType = ManagedDepartment
    init(managedObject: ManagedDepartment) {
        self.name = managedObject.name
    }
}

class CoreDataStore<ManagedObject: ManagedObjectProtocol, DataObject: DataProtocol> {

    func fetchSomeObject() -> DataObject {
        var managedObject: ManagedObject // fetch an NSManagedObject

        // Error here
        return DataObject(managedObject: managedObject)
    }

}

我收到的错误是当我尝试初始化 fetchSomeObject 中的结构时:

Cannot invoke initializer for type 'DataObject' with an argument list of type '(managedObject: ManagedObject)'

显然,编译器无法确定 DataObject(仅限于符合 DataProtocol 的类型)可以使用 ManagedObject 进行初始化>(仅限于符合 ManagedObjectProtocol 的类型)尽管它在 DataProtocol 中被声明为此类。

有什么办法可以实现这个功能吗?此外,这是一种合理的方法还是我完全不接受这种方法?

更新

经过一番挖掘,似乎 Swift generics are invariant我认为这是导致我遇到的问题。

最佳答案

想想你的 CoreDataStore再次,例如,CoreDataStore<ManagedPerson, Department>没有任何意义。为什么不?因为DepartmentDataProtocol没问题,但它对应的类型别名 ManagedObjectType不是 ManagedPerson .

您的代码无法编译的原因是一样的。这里return DataObject(managedObject: managedObject)你不能初始化 DataObject来自 armbitary ManagedObject , 只有一个 DataObject.ManagedObjectType是可以接受的。

所以你需要的是一个类型约束,添加这个 where 子句,你的代码应该可以工作:

class CoreDataStore<ManagedObject: ManagedObjectProtocol, DataObject: DataProtocol
    where DataObject.ManagedObjectType == ManagedObject>

关于ios - 以 "generic"方式将 NSManagedObject 转换为结构体 (Swift),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33218100/

相关文章:

objective-c - Objective-C : Drawing with Fingers on UIScrollView

objective-c - 在我的 UITableView 中滚动时,单元格正在消失

ios - 从 UIView 调用共享表

ios - 如何使用 Swift 解决 Firebase 中的异步问题?

json - 在 JSON 中使用 nil 而不是 Optional(<null>) 作为空值

ios - 在 UIViewController 之间切换时会发生什么类型的内存问题?

ios - UIImage 在模拟器上工作,但在设备上 swift 崩溃

java - 以原子方式确保 ConcurrentMap 条目

java - 如何将泛型类扩展为泛型类

c# - 列表和集合的通用约束