Reputation: 3582
So I'm a bit dismayed that Apple has replaced a transparent, easy-to-handle NSUInteger
with an HKQueryAnchor
but has not provided an easy way to persist that HKQueryAnchor
. Has anyone found a good way to do this with NSUserDefaults
? The only persistence method I have seen is an archiver to a local file, but my app persists everything in NSUserDefaults
, and I'd like to keep it that way if possible. Is there a reliable way to store an HKQueryAnchor
this way?
Upvotes: 3
Views: 1123
Reputation: 598
This answer is building off @allmightu 's answer, but without the SwiftUI @AppStorage
requirement. I also packaged it into a nice get/set syntax, so this is pretty much invisible to any consumer of the variable.
let anchorKey = "defaults-anchor-key"
var anchor: HKQueryAnchor? {
get {
guard let anchorData = UserDefaults.standard.data(forKey: anchorKey) else {
return nil
}
return try? NSKeyedUnarchiver.unarchivedObject(ofClass: HKQueryAnchor.self, from: anchorData)
}
set {
guard let newValue = newValue else {
UserDefaults.standard.set(nil, forKey: anchorKey)
return
}
if let anchorData = try? NSKeyedArchiver.archivedData(withRootObject: newValue, requiringSecureCoding: true) {
UserDefaults.standard.set(anchorData, forKey: anchorKey)
}
}
}
Upvotes: 0
Reputation: 1
You can declare the anchor as a computed variable which decodes the Data that you store in NSUserDefaults
using NSKeyedUnarchiver
@AppStorage("anchorKey") private var encodedAnchor: Data?
private var myAnchor: HKQueryAnchor? {
if let encodedAnchor {
// Decode the data to get HKQueryAnchor
if let decodedAnchor = try? NSKeyedUnarchiver.unarchivedObject(ofClass: HKQueryAnchor.self, from: encodedAnchor){
return decodedAnchor
}
}
return nil
}
On your HKAnchoredObjectQuery
, you can then encode the newAnchor which the closure provides using NSKeyedArchiver
which stores it to your stored value using NSUserDefaults
if let newEncodedAnchor = try? NSKeyedArchiver.archivedData(withRootObject: newAnchor, requiringSecureCoding: true) {
// Store the encoded anchor data in UserDefaults
self.myAnchor = newEncodedAnchor
}
Upvotes: 0
Reputation: 9825
You can convert it to NSData
using NSKeyedArchiver
and store that in the user defaults.
To store:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:anchor];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"AnchorData"];
To retrieve:
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"AnchorData"];
HKQueryAnchor *anchor = [NSKeyedUnarchiver unarchiveObjectWithData:data];
Upvotes: 7