我在iOS上使用RealmSwift的应用程序存储了少量数据。每隔约5分钟左右,通过CloudKit推送通知更新数据。
除了我的Realm文件不断增长,直到应用程序不再有足够的内存才能启动时,它才有效。
我设法使用" writeCopy"稍微解决了这个问题。在发布时压缩领域的功能 - 如果应用程序半频繁停止以便有机会运行,这通常有效,但如果没有发生这种情况,应用程序将继续通过后台推送通知更新数据有些日子,数据库会变得太大而压缩它需要年龄,或者只是崩溃尝试。
我试过阅读"文件大小"常见问题解答中的部分,但我不认为我完全理解导致规模增长的规则。它提到了保持"旧领域" open - 这是否意味着Realm例如"让领域=尝试!境界()"或者它真的意味着任何开放的对象?
如果是后者那么这很烦人,因为我在后台使用结果集上的通知来确定何时更新配套监视应用程序上的复杂功能。
我非常喜欢领域,我想坚持下去,但我觉得我有点不寻常的用例(长时间运行的应用程序经常在后台更新)可能意味着我无法使用它。
编辑:
背景更新是由于'didReceiveRemoteNotification' app delegate callback,像这样:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let dict = userInfo as! [String: NSObject]
let notification = CKNotification(fromRemoteNotificationDictionary: dict)
if notification.notificationType == .query {
let notification = notification as! CKQueryNotification
if let recordID = notification.recordID {
let requestOperation = CKFetchRecordsOperation(recordIDs: [recordID])
requestOperation.fetchRecordsCompletionBlock = { records, error in
if let error = error {
os_log("Error fetching record: %@", log: Logger.default, type: .error, String(describing: error))
} else {
autoreleasepool {
let realm = try! Realm()
try! realm.write {
records?.forEach { (key, record) in
switch record.recordType {
case "Freeway":
let dict = RealmFreeway.dictionary(from: record)
realm.create(RealmFreeway.self, value: dict, update: true)
case "Segment":
let dict = RealmSegment.dictionary(from: record)
realm.create(RealmSegment.self, value: dict, update: true)
default:
os_log("Unknown record type: %@", log: Logger.default, type: .error, record.recordType)
}
}
}
}
}
}
CKContainer.default().publicCloudDatabase.add(requestOperation)
}
}
completionHandler(.newData)
}
手表复杂功能通过RxSwift更新如下:
Observable.combineLatest(watchViewModel.freewayName.asObservable(), watchViewModel.startName.asObservable(), watchViewModel.endName.asObservable(), watchViewModel.travelTime.asObservable(), watchViewModel.color.asObservable(), watchViewModel.direction.asObservable()) {
freewayName, startName, endName, travelTime, color, direction -> [String:Any] in
guard let freewayName = freewayName,
let startName = startName,
let endName = endName,
let direction = direction else {
return [String:Any]()
}
let watchData:[String:Any] = [
"freewayName": freewayName,
"startName": startName,
"endName": endName,
"travelTime": travelTime,
"color": color.htmlRGBColor,
"direction": direction,
"transfers": session.remainingComplicationUserInfoTransfers
]
return watchData
}
.filter { $0.keys.count > 0 }
.throttle(2.0, scheduler: MainScheduler.instance)
.subscribe( onNext: { watchData in
let MIN_DURATION = 24.0 * 60.0 * 60.0 / 50.0 // 50 guaranteed updates per day...
var timeSinceLastUpdate = MIN_DURATION
let now = Date()
if let lastUpdated = self.lastComplicationUpdate {
timeSinceLastUpdate = now.timeIntervalSince(lastUpdated)
}
// Should we use a complication update or an application context update?
let complicationUpdate = timeSinceLastUpdate >= MIN_DURATION
// Send the data via the appropriate method.
if complicationUpdate {
session.transferCurrentComplicationUserInfo(watchData)
} else {
try? session.updateApplicationContext(watchData)
}
self.lastComplicationUpdate = now
})
.addDisposableTo(bag)