gpt4 book ai didi

swift - 在 Swift 中创建通用 Realm 存储库

转载 作者:可可西里 更新时间:2023-11-01 00:57:30 26 4
gpt4 key购买 nike

我一直在努力解决一个问题,我很确定这个问题让我采用了类型删除技术,但我不是 100% 确定。我尝试了好几次,感觉很亲近,但最终都失败了。我会尽量简化我的问题。假设您有一个实体

struct Expense {
var id: Int?
var amount: Double = 0
}

和一个等效的 Realm 对象

class RealmExpense: Object {
let id = RealmOptional<Int>()
let amount = RealmOptional<Double>()

var entity: Expense {
return Expense(id: id.value, amount: amount.value)
}
}

请注意,我可以使用实体变量将 RealmExpense 转换为 Expense。

然后,我有另一个协议(protocol)

protocol ExpenseRepository: class {
func getAll() -> [Expense]
//...other CRUD methods
}

最后是一个类

class ExpenseRealmRepository: ExpenseRepository {

private let realm = try! Realm()

func getAll() -> [Expense] {
return realm.objects(RealmExpense.self).flatMap { $0.entity }
}

func insert(item: Expense) {
try! realm.write {
realm.add(RealmExpense(expense: item))
}
}
//...implementation of other CRUD methods
}

现在,这工作正常,但我有很多实体,这是我想重构的重复代码,但我为使这个泛型所做的每一次尝试都会抛出一个或另一个编译器错误。我想要的是基本上能够创建一个类

class RealmRepository<RepositoryType: Object, EntityType> {

private let realm = try! Realm()

func getAll() -> [EntityType] {
return realm.objects(RepositoryType.self).flatMap { $0.entity }
}

func insert(item: EntityType) {
try! realm.write {
realm.add(RepositoryType(item))
}
}
//...the rest of the CRUD methods.
}

我的主要问题是 Swift 泛型似乎不允许这种行为。也许有一个我还没有探索过的更好的整体方法。

注意:下面是 Dave Weston 的回答的小附录:

下面 David Weston 给出的答案是正确的(而且非常好),但是目前有一个 Swift 错误阻止使用 Realm 实体初始化程序。见:

https://github.com/realm/realm-cocoa/pull/2514

基本上,解决方案是为接受字典的 Realm 对象使用默认初始化程序。由于我已经在使用 ObjectMapper 库将实体与 JSON 相互转换,这就像更改一样简单

func insert(item: T.EntityType) {
realm.write {
realm.add(RealmEntityType(item)) //compiler error when initializing RealmEntityType
}
}

func insert(item: T.EntityType) {
let realmItem = RealmEntityType()
realmItem.setValuesForKeys(item.toJSON()) //needs to be a dictionary
try! realm.write {
realm.add(realmItem)
}
}

最佳答案

这是一个有趣的问题。我不确定您将如何使用这些存储库对象,但根据您目前的问题,我不需要使用类型删除。

首先,我们定义我们需要的通用层次结构:

// implemented by your immutable structs
protocol Entity {
}

// Implemented by RealmSwift.Object subclasses
protocol RealmEntity {
associatedtype EntityType

init(_ entity: EntityType)
var entity: EntityType { get }
}

// protocol to define the operations one can perform on a repository
protocol Repository {
associatedtype EntityType

func getAll() -> [EntityType]
func insert(item: EntityType)
}

// A RealmRepository that implements the Repository protocol on top of Realm
class RealmRepository<T>: Repository where T: RealmEntity, T: Object, T.EntityType: Entity {
typealias RealmEntityType = T

private let realm = Realm()

internal func insert(item: T.EntityType) {
realm.write {
realm.add(RealmEntityType(item))
}
}

internal func getAll() -> [T.EntityType] {
return realm.objects(T.self).flatMap { $0.entity }
}
}

现在我们有了基础设施,我们可以创建一个 ExpenseRepository 来显示所有这些东西都可以编译:

struct Expense: Entity {
var id: Int
var amount: Double
}

class RealmExpense: Object, RealmEntity {
typealias EntityType = Expense

let id: RealmOptional<Int>
let amount: RealmOptional<Double>

required init(_ entity: EntityType) {
id = RealmOptional(entity.id)
amount = RealmOptional(entity.amount)
}

var entity: Expense {
return Expense(id: id.value!, amount: amount.value!)
}
}

var expenseRepository = RealmRepository<RealmExpense>()

这可能无法在您的项目中编译,因为我是在未导入 Realm 的 Playground 中创建的,但它应该会给您一个想法。

现在,如果你想存储不同类型的存储库数组,或者存储库类型的变量,那么你就需要类型删除,并且必须创建一个 AnyRepository .

关于swift - 在 Swift 中创建通用 Realm 存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42369333/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com