提问人:Aniket Rao 提问时间:10/20/2023 最后编辑:HangarRashAniket Rao 更新时间:10/21/2023 访问量:40
iOS Swift 中 CoreData 的 iCloud Backup for .sqlite 数据库文件
iCloud Backup for .sqlite database file for CoreData in iOS Swift
问:
我目前正在从事一个 iOS 项目,其中我使用 Core Data 进行本地数据存储。现在,我想将我的.sqlite数据库文件上传到iCloud,以便进行同步和备份。有人可以指导我完成此任务的步骤和最佳实践吗?
- 如何配置我的核心数据堆栈以与 iCloud 配合使用?
- 以编程方式将我的 .sqlite 数据库文件上传到 iCloud 云盘的步骤是什么?
- 在处理 iCloud 和 Core Data 集成时,是否有任何注意事项或潜在问题需要注意?
我在这里附上我的备份文件代码块。
class BackUp : NSObject {
var query: NSMetadataQuery!
let iCloudContainerIdentifier = "-----------"
private let databaseName = "projectName.sqlite"
let container = NSPersistentContainer(name: "projectName")
override init() {
super.init()
initialiseQuery()
addNotificationObservers()
}
func initialiseQuery() {
query = NSMetadataQuery.init()
query.operationQueue = .main
query.searchScopes = [NSMetadataQueryUbiquitousDataScope]
query.predicate = NSPredicate(format: "%K LIKE %@", NSMetadataItemFSNameKey, databaseName)
}
private func retrieveLocalURL() -> URL {
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
let documentaryDirectory = urls[0]
let realmURL = documentaryDirectory.appendingPathComponent("Yoodoo.sqlite");
return realmURL
}
func startBackup() throws {
let fileURL = retrieveLocalURL()//Bundle.main.url(forResource: "projectName", withExtension: "sqlite") else { return }
if let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: iCloudContainerIdentifier) {
if !FileManager.default.fileExists(atPath: containerURL.path) {
try FileManager.default.createDirectory(at: containerURL, withIntermediateDirectories: true, attributes: nil)
}
let backupFileURL = containerURL.appendingPathComponent(databaseName)
if FileManager.default.fileExists(atPath: backupFileURL.path) {
try FileManager.default.removeItem(at: backupFileURL)
try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
} else {
try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
}
query.operationQueue?.addOperation({ [weak self] in
_ = self?.query.start()
self?.query.enableUpdates()
})
} else{
print("Container Not Found...!")
}
// guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: iCloudContainerIdentifier) else { return }
}
func addNotificationObservers() {
NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryDidStartGathering, object: query, queue: query.operationQueue) { (notification) in
self.processCloudFiles()
}
NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryDidUpdate, object: query, queue: query.operationQueue) { (notification) in
self.processCloudFiles()
}
}
@objc func processCloudFiles() {
if query.results.count == 0 { return }
var fileItem: NSMetadataItem?
var fileURL: URL?
for item in query.results {
guard let item = item as? NSMetadataItem else { continue }
guard let fileItemURL = item.value(forAttribute: NSMetadataItemURLKey) as? URL else { continue }
if fileItemURL.lastPathComponent.contains(databaseName) {
fileItem = item
fileURL = fileItemURL
}
}
let fileValues = try? fileURL!.resourceValues(forKeys: [URLResourceKey.ubiquitousItemIsUploadingKey])
if let fileUploaded = fileItem?.value(forAttribute: NSMetadataUbiquitousItemIsUploadedKey) as? Bool, fileUploaded == true, fileValues?.ubiquitousItemIsUploading == false {
print("backup upload complete")
} else if let error = fileValues?.ubiquitousItemUploadingError {
print("upload error---", error.localizedDescription)
} else {
if let fileProgress = fileItem?.value(forAttribute: NSMetadataUbiquitousItemPercentUploadedKey) as? Double {
print("uploaded percent ---", fileProgress)
}
}
}
func restoreBackup() throws {
guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: iCloudContainerIdentifier) else {
print("Container Not Found...!")
return
}
let backupFileURL = containerURL.appendingPathComponent(databaseName)
if FileManager.default.fileExists(atPath: backupFileURL.path) {
let localURL = retrieveLocalURL()
do {
if FileManager.default.fileExists(atPath: localURL.path) {
try FileManager.default.removeItem(at: localURL)
}
try FileManager.default.copyItem(at: backupFileURL, to: localURL)
print("Data restored successfully.")
} catch {
print("Failed to restore data: \(error.localizedDescription)")
}
} else {
print("Backup file not found in iCloud.")
}
}
}
- 我已经在 Xcode 中启用了 iCloud 的功能,并且还创建了手动和自动这两个 iCloud 容器来存储数据。
- 此外,我还尝试了使用不同类型的数据库对象(如privateDatabase和Public Database)的不同函数。
期望:
- 我希望整个 .sqlite 数据库文件(包含所有表)应该上传到 iCloud 上,每当我们再次安装应用程序并且 iCloud 上存在 .sqlite 数据库文件时,它应该替换为本地文件。
答: 暂无答案
评论