Hi -
My client app (IOS app using ParseSwift v4.14.2) needs to save data to the local Parse instance while the app is offline. The example:
- The app connects to a bluetooth device
- The app logic wants to record the timestamp of the connection in Parse
- The Parse initialization configuration includes [requestCachePolicy: .returnCacheDataElseLoad]
- The app logic can successfully query the Parse db and retrieve the correct object using an explicit cachePolicy( .returnCacheDataElseLoad)
- Values on the returned object can be changed.
- The updated object cannot be saved using save()
- I have tested using multiple cachePolicy settings but with no success
The code:
Client side parse initialization
private func initializeParse() {
ParseSwift.initialize(
applicationId: CONST_PARSE_LOG_SERVER_APP_ID,
serverURL: URL(string: CONST_PARSE_LOG_SERVER_URL)!,
usingTransactions: false,
usingEqualQueryConstraint: false,
usingPostForQuery: false,
requestCachePolicy: .returnCacheDataElseLoad ,
cacheMemoryCapacity: 512_000,
cacheDiskCapacity: 10_000_000
)
}
App logic:
public func logDeviceConnection(uuid: String) {
let newConnection = Int64(Date().timeIntervalSince1970)
var options = API.Options()
options.insert(.cachePolicy( .returnCacheDataElseLoad ))
let query = Snap.query("device_uuid" == uuid)
query.first(options: options) { result in // << note the cache policy on query works
switch result {
case .success(let foundDevice): // << this works with no network connection
// found the correct device, make mergeable
var deviceToSave = foundDevice.mergeable
// set the new timestamp on the last_connection member
deviceToSave.last_connection = newConnection
// atempt to save device
deviceToSave.save(options: options) { attemptSave in
switch attemptSave {
case .success(let savedDevice):
print("Woo hoo! Saved the new timestamp: \(savedDevice)")
case .failure(let error):
print("Doh. Unable to save new timestamop: \(error) ") // << always fails
}
}
case .failure(let returnedError):
print("Error: Unable to fetch Parse object.")
}
}
Error: “Resource Unavailable”
2022-10-15 12:17:30.514212-0700 CadioTesting[3808:819334] Task <A3AF8CFE-408F-47C1-97AF-6B4C71F71131>.<13> finished with error [-1008] Error Domain=NSURLErrorDomain Code=-1008 "resource unavailable" UserInfo={NSLocalizedDescription=resource unavailable, NSErrorFailingURLStringKey=http://sneakersnaps.com/parse/classes/Snap/RqMR8wxqdP, NSErrorFailingURLKey=http://sneakersnaps.com/parse/classes/Snap/RqMR8wxqdP, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <A3AF8CFE-408F-47C1-97AF-6B4C71F71131>.<13>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <A3AF8CFE-408F-47C1-97AF-6B4C71F71131>.<13>, NSUnderlyingError=0x280d99a70 {Error Domain=kCFErrorDomainCFNetwork Code=-1008 "(null)"}}
Doh. Unable to save new timestamop: ParseError code=-1 error=Unable to connect with parse-server: Error Domain=NSURLErrorDomain Code=-1008 "resource unavailable" UserInfo={NSLocalizedDescription=resource unavailable, NSErrorFailingURLStringKey=http://sneakersnaps.com/parse/classes/Snap/RqMR8wxqdP, NSErrorFailingURLKey=http://sneakersnaps.com/parse/classes/Snap/RqMR8wxqdP, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <A3AF8CFE-408F-47C1-97AF-6B4C71F71131>.<13>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <A3AF8CFE-408F-47C1-97AF-6B4C71F71131>.<13>, NSUnderlyingError=0x280d99a70 {Error Domain=kCFErrorDomainCFNetwork Code=-1008 "(null)"}}
Research:
I’ve looked at Parse source code for save(). In the synchronous save() case [see ParseObject file, line 1164] there is an additional function named ensureDeepSave() that is called. If you follow that function you come to line 1411 in ParseObject and there is this comment:
// Remove any caching policy added by the developer as fresh data
// from the server is needed.
options.remove(.cachePolicy(.reloadIgnoringLocalCacheData))
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))
So the code is overriding my caching selections. Ok hmmm…
In the asynchronous case save() [ParseObject line 1202] the code does not appear to call ensureDeepSave but I still get the error.
Additional thoughts:
- perhaps my cache is full, over 10meg and that’s causing the error?
- I’m missing a client side config parameter that allows for query but not save?
- there is a server side config parameter that I’m not aware of?
- Obj C version looks like it has a ‘pinning’ feature that ParseSwift doesn’t have
Anyone successfully saving with cachePolicy(.returnCacheDataDontLoad) or .returnCacheDataElseLoad?
thank you!