Closed LiamDeGrey closed 9 months ago
Hi. Thanks for the issue. I think I also ran into this here #21, and related to an issue with okio
Can you share how the store was created? Is there a reproducer somewhere?
Initially I thought this was a different issue to #21, but I think you're right - both crashes are getting caught up at
okio.PosixFileSystem#sink
I'm happy for this discussion to be transferred to #21.
In reference to this potential Okio solution:
May be related to data protection caused by Passcode set on the Device's Settings. If the fopen is called when the device was locked and passcode is needed, "Operation not permitted" will be returned.
This was not the case for me - I can consistently reproduce the issue using my physical iPhone 14 Pro device while unlocked and in-use.
Related code:
FilePath for an iOS target is:
"${NSHomeDirectory()}/$fileName.json"
Thanks for the info. I think i'll keep this issue open and close my original one as there's more information here.
As for a fix, I'll follow up with okio - looks like there's a callback in AppDelegate
that announces when applicationProtectedDataDidBecomeAvailable
, whatever that means. With this, the store can handle this safely hopefully
Is there a work around?
The workaround I've found is to manually create the file with the correct empty JSON contents if it doesn't already exist.
Something like:
actual fun pathTo(subPath: String, startingTag: String): String {
val fileManager = NSFileManager.defaultManager
val directoryUrl = NSURL.fileURLWithPath(NSHomeDirectory()) // or NSURL.fileURLWithPath(NSSearchPathForDirectoriesInDomains(NS<Whatever>Directory, NSUserDomainMask, true).firstOrNull().toString())
val fileUrl = directoryUrl.URLByAppendingPathComponent(subPath)!!
val filePath = fileUrl.path!!
if (!fileManager.fileExistsAtPath(filePath)) {
fileManager.createFileAtPath(
filePath,
(startingTag as NSString).dataUsingEncoding(NSUTF8StringEncoding),
null
)
}
return filePath
}
If your store item is a single object, pass startingTag = "{}"
. If it's a list, pass startingTag = []
.
Hmm, this did not seem to work for me over here. @zacharee do you know which version of kstore you used?
0.6.0
Hey I guess I ran into the same problem and wanted to let you know that @zacharee s workaround is not working for me either. Does anyone have any other suggestions?
I tried to find a solution and asked in the ios Channel of the Kotlin Slack Community. Konstantin Tskhovrebov suggested to use the NSCachesDirectory
as the filePath
which can be obtained like this:
private fun getCacheDirectoryPath(): Path {
val cacheDir = NSSearchPathForDirectoriesInDomains(
NSCachesDirectory,
NSUserDomainMask,
true
).first() as String
return "$cacheDir/cache".toPath()
}
For me it worked this way. (Disclaimer: I switched to using okio directly, so I dont know if it works for KStore as well, but I guess because KStore uses okio it should)
Hi @linde9821 Thanks for your findings! I'll add some convenience extension methods to address NSDocumentsDirectory
via NSFileManager
Fixed in 0.7.1!
[!WARNING] Avoid creating files at
NSHomeDirectory
! Though it works on the simulator, is not suitable for physical devices as the security policies on physical devices do not permit read/write to this directory
Use either
// for documents directory
storageDir = NSFileManager.defaultManager.DocumentDirectory?.relativePath
// or caches directory
storageDir = NSFileManager.defaultManager.CachesDirectory?.relativePath
Updated docs: https://xxfast.github.io/KStore/using-platform-paths.html#on-ios-other-apple-platforms
Dependencies![image](https://user-images.githubusercontent.com/7564057/236414785-1b7a6d6c-70f9-46f8-8420-6b7c3be171aa.png)
Device details iPhone 14 Pro - 16.4.1 (a)
There is no issue when running on an iPhone 14 Pro simulator running 16.4