【问题标题】:Clear complete Realm Database清除完整的领域数据库
【发布时间】:2014-11-21 21:58:12
【问题描述】:

我正在使用领域(当前为 0.85.0),我的应用程序使用数据库来存储特定于用户的数据,例如当前用户的联系人。当用户决定注销时,我需要删除有关用户的每一点信息,而在我看来,最明显、最简单和最干净的事情就是擦除整个领域。不幸的是,Cocoa 库不提供该功能。

目前,我遇到了以下问题

RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm deleteObjects:[MyRealmClass1 allObjectsInRealm:realm]];
[realm deleteObjects:[MyRealmClass2 allObjectsInRealm:realm]];
[realm deleteObjects:[MyRealmClass3 allObjectsInRealm:realm]];
[realm commitWriteTransaction];

有更好的想法吗?

谢谢

【问题讨论】:

    标签: ios realm


    【解决方案1】:

    你也可以去你的realm文件存放的位置,从那里删除那个文件,下次运行app后打开realm时,你会在浏览器中看到空的realm数据库。

    【讨论】:

      【解决方案2】:

      RealmSwift:使用标志进行简单重置

      尝试了上述答案,但发布了一种更简单的方法来删除领域文件而不是迁移:

      Realm.Configuration.defaultConfiguration.deleteRealmIfMigrationNeeded = true
      

      这只是设置一个标志,以便 Realm 可以删除现有文件,而不是在 try! Realm() 上崩溃

      而不是手动删除文件

      认为这比上述答案的 Swift 版本更简单:

      guard let path = Realm.Configuration.defaultConfiguration.fileURL?.absoluteString else {
          fatalError("no realm path")
      }
      
      do {
          try NSFileManager().removeItemAtPath(path)
      } catch {
          fatalError("couldn't remove at path")
      }
      

      【讨论】:

      • 我不知道具体是在哪个版本中引入的,但现在使用 deleteRealmIfMigrationNeeded 实际上是正确的方法。
      【解决方案3】:

      更新:

      自发布以来,添加了一个新方法来删除所有对象(正如 jpsim 已经提到的):

      // Obj-C
      [realm beginWriteTransaction];
      [realm deleteAllObjects];
      [realm commitWriteTransaction];
      
      
      // Swift
      try! realm.write {
        realm.deleteAll()
      }
      

      请注意,这些方法不会改变数据结构;他们只删除现有记录。如果您希望在不编写迁移的情况下更改领域模型属性(即,就像您在开发中所做的那样),下面的旧解决方案可能仍然有用。

      原答案:

      您可以简单地删除领域文件本身,就像他们在sample code for storing a REST response 中所做的那样:

      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
      {
          //...
      
          // Ensure we start with an empty database
          [[NSFileManager defaultManager] removeItemAtPath:[RLMRealm defaultRealmPath] error:nil];
      
          //...
      }
      

      关于您的评论的更新:

      如果您需要确保不再使用领域数据库,您可以使用领域的通知。如果您要在每次写入之前增加一个 openWrites 计数器,那么您可以在每次写入完成时运行一个块:

      self.notificationToken = [realm addNotificationBlock:^(NSString *notification, RLMRealm * realm) {
          if([notification isEqualToString:RLMRealmDidChangeNotification]) {
              self.openWrites = self.openWrites - 1;
      
              if(!self.openWrites && self.isUserLoggedOut) {
                  [[NSFileManager defaultManager] removeItemAtPath:[RLMRealm defaultRealmPath] error:nil];
              }
          }
      }];
      

      【讨论】:

      • 是的,我已经尝试过了,但问题是当后台有一些线程在用户决定注销时尝试在领域做某事时,这种方法会变得非常讨厌。删除磁盘上的文件的缺点是它会忽略当前可能打开的事务并最终导致应用程序崩溃。而且我真的不想开始同步我所有的数据库访问.. 无论如何谢谢:)
      • 嗨,来自 Realm 的 Tim。 DonamiteIsTnt 的想法是正确的,但你说得对,这种方法存在一些极端情况。我们将很快介绍一种以安全方式删除领域文件的方法。对此感到抱歉!
      • @timanglade 关于这种方法的进展有什么消息吗?我似乎找不到它,但能够删除和重新创建领域文件将是一个很棒的功能
      • 啊,谢谢...我有点希望你的意思是删除文件的 api。我们只将它用作缓存,删除/重新创建文件比处理迁移更容易。
      【解决方案4】:

      我遇到了这个有趣的小问题。因此,我在运行架构迁移之前直接查询架构版本。

      NSError *error = NULL;
      NSUInteger currentSchemaVersion = [RLMRealm schemaVersionAtPath:[RLMRealm defaultRealmPath] error:&error];
      if (currentSchemaVersion == RLMNotVersioned) {
          // new db, skip
      
      } else if (currentSchemaVersion < 26) {
          // kill local db
          [[NSFileManager defaultManager] removeItemAtPath:[RLMRealm defaultRealmPath] error:&error];
          if (error) {
              MRLogError(error);
          }
      
      } else if (error) {
          // for good measure...
          MRLogError(error);
      }
      
      // perform realm migration
      [RLMRealm setSchemaVersion:26
                  forRealmAtPath:[RLMRealm defaultRealmPath]
              withMigrationBlock:^(RLMMigration *migration, NSUInteger oldSchemaVersion) {
      
              }];
      

      【讨论】:

        【解决方案5】:

        从领域 0.87.0 开始,现在可以通过在写入事务中调用 [[RLMRealm defaultRealm] deleteAllObjects] 来删除所有领域内容。

        在 Swift 中,它看起来像这样:RLMRealm.defaultRealm().deleteAllObjects()

        【讨论】:

        • 如果有待迁移,此选项将不起作用。如果您想绕过迁移,请使用 @DonamiteIsTnt 答案
        【解决方案6】:

        如果有人偶然发现这个问题,正在寻找一种在 Swift 中执行此操作的方法,这只是 DonamiteIsTnt 的答案重写。我已将此函数添加到自定义实用程序类中,因此我可以在测试和调试期间执行MyAppUtilities.purgeRealm()

        func purgeRealm() {
            NSFileManager.defaultManager().removeItemAtPath(RLMRealm.defaultRealmPath(), error: nil)
        }
        

        注意:如果您发现自己需要清除数据,您可以查看 Realm 的新 realm.addOrUpdateObject() 功能,该功能允许您将现有数据的主键替换为新数据。这样您就不会不断地添加新数据。只是替换“旧”数据。如果您确实使用了addOrUpdateObject(),请确保覆盖模型的primaryKey 类函数,以便Realm 知道哪个属性是您的主键。以 Swift 为例:

        override class func primaryKey() -> String {
            return "_id"
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-24
          • 1970-01-01
          • 2017-03-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多