备份领域到iCloud Drive

时间:2017-01-27 14:51:51

标签: ios objective-c swift realm

我想将一个领域数据库文件备份到一个iCloud驱动器,比如WhatsApp,我有一些问题:

  1. 这样做的最佳做法是什么?

  2. 我有一个位于共享组文件夹中的数据库,可以从扩展程序访问它,我该如何备份它?如何显示上传的进度条?像WhatsApp一样?

  3. 如果我将一个领域文件放在一个文档文件夹中,它将同步进行每次修改。

  4. 我们可以看到一些示例代码吗?

  5. 感谢您的帮助,有什么想法吗?链接?

4 个答案:

答案 0 :(得分:8)

为了澄清,这是一个关于将离散Realm文件本身备份到iCloud Drive的问题,以便它可以在iCloud Drive应用程序中看到。不将文件内容同步到CloudKit商店。

如果将Realm文件保留在Documents目录中,则如果用户执行iCloud或iTunes备份,则将备份该文件。所有这些意味着,如果用户决定升级到新设备并使用旧设备的备份映像执行还原,则将恢复Realm文件。如果用户在此之前从旧设备中删除了应用程序,则iCloud备份也将被删除。

如果您要导出您的Realm文件,以便可以在iCloud Drive中永久保存和访问它,您可以将Realm文件的副本导出到您应用的iCloud ubiquity container。这基本上只是另一个文件夹,如共享组的文件夹,但它由iCloud管理。此文件夹的行为类似于Dropbox,因为您放入的任何内容都会自动同步。

代码看起来像这样:

let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)
let realmArchiveURL = containerURL.appendPathComponent("MyArchivedRealm.realm")

let realm = try! Realm()
try! realm.writeCopy(toFile: realmArchiveURL)

这是一个非常基本的例子。 Apple文档建议您在后台线程上执行此操作,因为首次设置iCloud文件夹可能会创建一些时间。

更新此功能不会自动发生。每次用户想要执行备份时,您都需要导出Realm的新副本。

答案 1 :(得分:2)

您可以mikemac8888查看this Github project

基本上,您使模型对象符合RealmCloudObject

class Note: Object, RealmCloudObject {
  ...
}

您必须实现映射功能:

func toRecord() -> CKRecord {
  ...
  record["text"] = self.text
  record["dateModified"] = self.dateModified
}

...以及用于从CloudKit记录中创建Realm记录的反向函数:

public func changeLocalRecord(...) throws {
  ...
  realm.create(objectClass as! Object.Type,
      value: ["id": id,
          "text": text,
          "dateModified": NSDate(),
          "ckSystemFields": recordToLocalData(record)],
      update: true)

  ...
}

完整的文档可以在我提供的链接上阅读,显然。

答案 2 :(得分:2)

我最近有相同的要求,并且可以通过以下步骤实现

快速键:4 +

步骤:1

Private items As New BindingList(Of String)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    ListBox1.DataSource = items
End Sub

Private Sub addButton_Click(sender As Object, e As EventArgs) Handles addButton.Click
    items.Add(TextBox1.Text)
End Sub

Private Sub deleteSelectedButton_Click(sender As Object, e As EventArgs) Handles deleteSelectedButton.Click
    items.RemoveAt(ListBox1.SelectedIndex)
End Sub

Private Sub deleteLastButton_Click(sender As Object, e As EventArgs) Handles deleteLastButton.Click
    items.RemoveAt(items.Count - 1)
End Sub

第2步

 1.Setup Your cloudKit for your app with a Developer account
 2. You can take reference: https://www.raywenderlich.com/1000-cloudkit-tutorial-getting-started 

第3步  -检查iPhone的“云启用”选项

 - Add CloudKit Capabilities in your App
 - Please check out the screenshot: https://prnt.sc/pdpda5

步骤4  -为本地或iCloud文档目录设置以下变量

// Return true if iCloud is enabled

func isCloudEnabled() -> Bool {
    if DocumentsDirectory.iCloudDocumentsURL != nil { return true }
    else { return false }
}

步骤:5 下面的函数用于copyRealmFileToIcloudContainer

struct DocumentsDirectory {
    static let localDocumentsURL = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: .userDomainMask).last!
    static let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents")
}

Step:6

func uploadDatabaseToCloudDrive()
{
    if(isCloudEnabled() == false)
    {
        self.iCloudSetupNotAvailable()
        return
    }

    let fileManager = FileManager.default

    self.checkForExistingDir()

    let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents", isDirectory: true)

    let iCloudDocumentToCheckURL = iCloudDocumentsURL?.appendingPathComponent("\(memberId)_default.realm", isDirectory: false)

    let realmArchiveURL = iCloudDocumentToCheckURL//containerURL?.appendingPathComponent("MyArchivedRealm.realm")

    if(fileManager.fileExists(atPath: realmArchiveURL?.path ?? ""))
    {
        do
        {
            try fileManager.removeItem(at: realmArchiveURL!)
            print("REPLACE")
            let realm = try! Realm()
            try! realm.writeCopy(toFile: realmArchiveURL!)

        }catch
        {
            print("ERR")
        }
    }
    else
    {
        print("Need to store ")
        let realm = try! Realm()
        try! realm.writeCopy(toFile: realmArchiveURL!)
    }
}

步骤:7  -确保已在info.plist中添加了以下几行

 - Once your realm file uploaded on the server , you can check this in your iPhone
 - Steps
     - 1.Go To Setting
     - 2.Go To iCloud
     - 3.Go To ManageStorage
     - 4.You will see your application there
     - 5.Tap on Application, you will able to see your realm file over there

答案 3 :(得分:2)

@yonlau根据您对备份领域文件的请求共享答案,此文件将进行一次测试,并且领域数据仅在备份到iCloud时才具有。

func DownloadDatabaseFromICloud()
{
    let fileManager = FileManager.default
    // Browse your icloud container to find the file you want
    if let icloudFolderURL = DocumentsDirectory.iCloudDocumentsURL,
        let urls = try? fileManager.contentsOfDirectory(at: icloudFolderURL, includingPropertiesForKeys: nil, options: []) {

        // Here select the file url you are interested in (for the exemple we take the first)
        if let myURL = urls.first {
            // We have our url
            var lastPathComponent = myURL.lastPathComponent
            if lastPathComponent.contains(".icloud") {
                // Delete the "." which is at the beginning of the file name
                lastPathComponent.removeFirst()
                let folderPath = myURL.deletingLastPathComponent().path
                let downloadedFilePath = folderPath + "/" + lastPathComponent.replacingOccurrences(of: ".icloud", with: "")
                var isDownloaded = false
                while !isDownloaded {
                    if fileManager.fileExists(atPath: downloadedFilePath) {
                        isDownloaded = true
                        print("REALM FILE SUCCESSFULLY DOWNLOADED")
                        self.copyFileToLocal()

                    }
                    else
                    {
                        // This simple code launch the download
                        do {
                            try fileManager.startDownloadingUbiquitousItem(at: myURL )
                        } catch {
                            print("Unexpected error: \(error).")
                        }
                    }
                }


                // Do what you want with your downloaded file at path contains in variable "downloadedFilePath"
            }
        }
    }
}

2。将领域文件从iCloud复制到文档目录

func copyFileToLocal() {
    if isCloudEnabled() {
        deleteFilesInDirectory(url: DocumentsDirectory.localDocumentsURL)
        let fileManager = FileManager.default
        let enumerator = fileManager.enumerator(atPath: DocumentsDirectory.iCloudDocumentsURL!.path)
        while let file = enumerator?.nextObject() as? String {

            do {
                try fileManager.copyItem(at: DocumentsDirectory.iCloudDocumentsURL!.appendingPathComponent(file), to: DocumentsDirectory.localDocumentsURL.appendingPathComponent(file))

                print("Moved to local dir")

                //HERE ACCESSING DATA AVAILABLE IN REALM GET FROM ICLOUD
                let realm =  RealmManager()
                let array = realm.FetchObjects(type: Mood.self)
                print(array?.count)

            } catch let error as NSError {
                print("Failed to move file to local dir : \(error)")
            }
        }
    }
}