ios 如何在Swift中分离领域对象

5rgfhyps  于 2023-10-21  发布在  iOS
关注(0)|答案(1)|浏览(102)

我们正在使用realm和,并希望分离realm Object s,即:创建对象的静态副本,该对象是一个Swift类/结构,可以独立于领域进行传递和修改。我们需要这样做有两个主要原因:
1.将持久层完全抽象化,所以没有文件需要使用realm Object,甚至导入RealmSwift包。
1.能够传递这些对象,有时甚至跨线程传递。(Realm对象不是线程安全的)

如何才能做到这一点?

我看到了两个“解决方案”,每个都有其不理想的原因(代码见下文):

方法1mapping realm objects to value types,手工编写所有CRUD操作,以及它们之间的Map。This article does a similar thing.然而,这两个帖子都非常古老(4+ & 6+年)和过时(根据领域文档:@Persisted声明样式替换了旧版本SDK中的@objc dynamic声明符号。"*)
*方法2创建一个“DetachableObject”协议,并为Object创建一个符合该协议的扩展,如下所示。但是这篇文章已经有7年的历史了,它并没有真正解决上面提到的原因1。
方法一

public struct Publisher {
    public let identifier: Int
    public let name: String
}
final class PublisherObject: Object {
    dynamic var identifier = 0
    dynamic var name = ""
    override static func primaryKey() -> String? {
        return "identifier"
    }
}
extension Publisher: Persistable {

    public init(managedObject: PublisherObject) {
        identifier = managedObject.identifier
        name = managedObject.name
    }

    public func managedObject() -> PublisherObject {
        let publisher = PublisherObject()

        publisher.identifier = identifier
        publisher.name = name

        return publisher
    }
}

// more see: https://gist.github.com/gonzalezreal/9d297c68435b9ee12bb1b009afd41d9a

方法二

protocol DetachableObject: AnyObject {

    func detached() -> Self

}

extension Object: DetachableObject {

    func detached() -> Self {
        let detached = type(of: self).init()
        for property in objectSchema.properties {
            guard let value = value(forKey: property.name) else { continue }
            if let detachable = value as? DetachableObject {
                detached.setValue(detachable.detached(), forKey: property.name)
            } else {
                detached.setValue(value, forKey: property.name)
            }
        }
        return detached
    }

}

extension List: DetachableObject {

    func detached() -> List<Element> {
        let result = List<Element>()
        forEach {
            result.append($0.detached())
        }
        return result
    }

}
6ie5vjzr

6ie5vjzr1#

我相信你问的是Realm对象的非托管版本。
如果是这样的话,就是这个过程:创建一个对象并将其持久化

class Person: Object {
   @Persisted var name = ""
}

let p = Person()
p.name = "Jay"

try! realm.write {
   realm.add(p)
}

稍后,我们需要一个Jay的非托管副本-它不与realm绑定,不存在,也不反映对Jay的任何更改,只存在于内存中

let jay = realm.objects(Person.self).where { $0.name == "Jay" }.first!

let unmanagedJay = Person(value: p)

//unmanagedJay is not Persisted and is flexible for doing what's needed with that object

这应该满足以下要求:1)完全抽象持久层,然后2)能够传递这些对象
我们在macOS应用中经常使用此过程,将on对象的非托管副本放置在例如UI中显示给用户的工作表中,可以自由操作而不会影响Realm或受Realm影响
你总是可以访问线程安全的冻结对象
冻结创建特定对象、集合或领域的不可变视图。冻结的对象、集合或领域仍然存在于磁盘上,并且在传递给其他线程时不需要进行深度复制。您可以在线程之间自由共享冻结对象,而无需担心线程问题。
同样,你也可以使用@Threadsafe属性 Package 器,它符合sendable并允许传递对象的线程限制示例。

相关问题