【问题标题】:Is it possible to make copy of Realm object?是否可以复制 Realm 对象?
【发布时间】:2016-11-28 14:38:03
【问题描述】:

我想在后台线程中刷新 Realm 数据库,如下所示: (因为我从 Webservice 得到了新鲜的数据)

 RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm deleteAllObjects]; // !!
[Pubs createOrUpdateInRealm:[RLMRealm defaultRealm] withJSONArray:data];
[realm commitWriteTransaction];

问题是,在我删除和更新 Realm db 中的对象的同时,用户可以打开一些 Detail ViewController 指向同时已被删除的某个 Realm 对象(Pubs),因此引发异常。

我没有看到任何解决方案,除非我想从 Detail 控制器或其属性访问 Realm 对象时,我总是需要这样做:

(这意味着总是获取 Realm 对象,但这也可能失败)

pub = [Pubs objectsWhere:[NSString stringWithFormat: @"pubId = %lu", (long)_selectedPubId]].firstObject;

但我没有使用这个解决方案。我想最好的办法是我可以在细节视图控制器中调用这样的东西:

pub = [Pubs objectsWhere:[NSString stringWithFormat: @"pubId = %lu", (long)_selectedPubId]].firstObject;
pub = [pub safeCopy];

所以可以同时删除PubRealmObject,但pub对象会单独存在于内存中(仅用于访问其数据属性)。

那么有人尝试过类似的方法吗?

或者甚至可能使用一些 iOS SDK 方式like this

如我所说,我只需要访问数据属性,而不是使用领域对象方法操作,例如删除或更新数据库中的对象。

顺便说一句,我试图在主线程中调用 Realm db 的更新,但问题是它需要 5-7 秒(只有 1000 个 JSON 对象),所以它滞后于应用程序。这就是为什么我认为对象的后台更新和安全复制可能会更好。

但我认为即使在复制对象时它也会失败,那么解决方案是什么? (后台更新 vs 安全访问 Realm 对象)

【问题讨论】:

    标签: ios realm


    【解决方案1】:

    让视图控制器依赖于可以从其下方删除的数据模型通常不是一个好的设计模式。可以通过检查其 object.invalidated 属性来检查 Realm 对象是否已被删除以避免异常。

    无论如何,要创建一个 Realm 对象的分离副本,您需要做的就是:

    RLMObject *copiedObject = [[RLMObject alloc] initWithValue:object];
    

    这将创建对象的副本,但不会插入到任何 Realm 实例中。请注意,如果对象链接到任何其他 Realm 对象,这些对象也不会被复制;新对象将只指向现有副本。

    但我仍然觉得我需要提及的是,您可能只是让您从 Web 服务更新 Realm 的实现更智能一些,以避免需要这样做。

    如果您的对象实现a primary key,那么当您调用createOrUpdateInRealm 时,现有对象将更新为新值。

    祝你好运!

    【讨论】:

    • 您好 TiM thx 回复。我会查一下。至于你是对的 createOrUpdateInRealm 方法,我有同样的想法,但我想这不会管理已删除的行。他们会留下来。所以我必须找到哪些被删除并删除它们,用户可以打开删除的一项,情况是一样的。但是,删除某些数据的情况可能很少见,这是事实。所以也许我可以选择那种方式。我会看到的。
    【解决方案2】:

    使用 Swift:

    以前回答过here

    截至 2020 年 12 月,此问题尚无适当的解决方案。不过我们有很多解决方法。

    这是我一直在使用的,我认为限制较少的一个。

    1. 使您的领域模型对象类符合可编码的要求
    class Dog: Object, Codable{
        @objc dynamic var breed:String = "JustAnyDog"
    }
    
    1. 创建这个帮助类
    class RealmHelper {
        //Used to expose generic 
        static func DetachedCopy<T:Codable>(of object:T) -> T?{
           do{
               let json = try JSONEncoder().encode(object)
               return try JSONDecoder().decode(T.self, from: json)
           }
           catch let error{
               print(error)
               return nil
           }
        }
    }
    
    1. 当您需要 Realm 对象的分离/真正的深层副本时调用此方法,如下所示:
     //Suppose your Realm managed object: let dog:Dog = RealmDBService.shared.getFirstDog()
     guard let detachedDog = RealmHelper.DetachedCopy(of: dog) else{
        print("Could not detach Note")
        return
     }
    //Change/mutate object properties as you want
     detachedDog.breed = "rottweiler"
    

    如您所见,我们使用 Swift 的 JSONEncoder 和 JSONDecoder,使用 Codable 的强大功能,无论我们的领域对象下有多少嵌套对象,都可以进行真正的深度复制。只需确保所有 Realm 模型类都符合 Codable。

    虽然它不是理想的解决方案,但它是最有效的解决方法之一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2018-04-17
      • 1970-01-01
      • 2015-12-16
      相关资源
      最近更新 更多