XHMM / react-native-cloud-store

A react-native module for icloud drive
https://react-native-cloud-store.vercel.app/docs/install/with-crna
MIT License
68 stars 11 forks source link

[Q][iOS] Any issue detected on iOS 17? #24

Closed williamliangwl closed 1 year ago

williamliangwl commented 1 year ago

So in our app, we have the functionality of checking if certain backup file exists in the user's iCloud. We do this by doing the following:

const files = await readDir();
return files.find(f => f === fileName);

During testing in production, there are 2 iOS 17 users where we have deleted the backup file in the iCloud, but the code it self says that the backup file still exists

I am just wondering if this is iOS 17 issue or other issue I am still finding a way to reproduce this as my iPhone is stuck on iOS 15

williamliangwl commented 1 year ago

https://developer.apple.com/forums/thread/733642

is this related ?

XHMM commented 1 year ago

How did you delete the backup files in your code? I tried on my iOS 17 phone: CloudStore.unlink() to delete and then called CloudStore.readDir() to retrive the files and the deleted file was not returned.

Can you provide a reproducible steps or repo for me to have a debug?

williamliangwl commented 1 year ago

We delete the backup in the iPhone by open Settings, click on profile, iCloud, Manage Storage, tap on the application we are debugging, Delete

williamliangwl commented 1 year ago

For the exact repro steps and logs, I'm still finding a way to debug it in iOs 17

XHMM commented 1 year ago

I haven't tried this way and I will have a test tonight.

williamliangwl commented 1 year ago

@XHMM do you manage to test this? I'm sorry I'm still unable to find iOS 17 device... I am currently using TestFlight to distribute test build to the affected user, but the feedback loop is taking very long time

XHMM commented 1 year ago

Sorry William I am busy with my work recently. I will test it later today.

You can also download xcode15 to test ios17 if you don't have a physical device to let us find the problem more quickly.

williamliangwl commented 1 year ago

Hi @XHMM , I managed to use iOS 17 simulator to test out this issue, but apparently the issue is not isolated to iOS 17 because the issue may also happen in iOS 16 simulator

A couple of questions though:

  1. When an app has uploaded a file to the iCloud, does it create or still store a local copy of the file ?
  2. If it still has, do we have a way to differentiate / to know when we do readDir and stat, if this file is a local copy or iCloud file?

Our observation shows that in some cases, when we delete the iCloud files using this way https://github.com/XHMM/react-native-cloud-store/issues/24#issuecomment-1762965266, and in the app we do readDir and stat on the files, the result of the stat is always

{
  isUploading: false,
  fileSize: 111,
  isDownloading: false,
  isUploaded: true,
  localizedName: "file_name_we_used_to_upload",
  isDirectory: false,
  downloadStatus: "NSURLUbiquitousItemDownloadingStatusCurrent",
  hasUnresolvedConflicts: false,
  isInICloud: true,
  hasCalledDownload: true,
}

so even though there's nothing in the iCloud, when we do stat, it always shows that.

XHMM commented 1 year ago
  1. When an app has uploaded a file to the iCloud, does it create or still store a local copy of the file ?

Yes, local file and iCloud file are two files, you need to delete the loca file manually if you don't want if after uploading

  1. If it still has, do we have a way to differentiate / to know when we do readDir and stat, if this file is a local copy or iCloud file?

I am not too clear about this question. Just differentiate files by the path, if it lives in iCloud, it's a cloud file, if it lives in your app folders(such as cache directory), it's a local file. For cloud files, you should call methods from CloudStore and for local files you shoud call methods from such as react-native-fs


And I tried as you said deleting files in the system settings, when I re-call stat() the file didn't exist as expected. I cannot reproduce what you said.

Are you sure you the path you passed to unlink() is the iCloud path but not the local path

williamliangwl commented 1 year ago

oh for the local file, what I mean is that we are using writeFile("file_path", "string_content", { override: true, onProgress: () => {} } to upload the string content to the iCloud. We have certain format for the file_path there.

When it comes to downloading, we do the following:

  1. Use readDir() to get all files
  2. From the result, use array.find to find the possible matching file name with the file_path stored
  3. Use stat() to know its downloadStatus
  4. call download() to start the download process
  5. when the progress is 100, call readFile with combination of PathUtils.iCloudRemoveDotExt
  6. return the content to the caller

The issue we are facing is that for some reason, although when the iCloud is empty already, the no 1 step, the readDir() still return the deleted file path and so that the code concludes that the file still exists

This issue is not always reproducible though. We tested in other device, they are working fine as you said

williamliangwl commented 1 year ago

1 question before I close this issue:

if we call download on not existed file url and listen to the onProgress, will it fail ?

somehow with the scenario above, I tried to force download the file even though its downloadStatus is NSURLUbiquitousItemDownloadingStatusCurrent, but it seems like because the file doesn't really exist in iCloud, the onProgress never reaches 100 but never fails too

I was thinking to add timeout to handle this but it is going to be a "magic number" workaround where it might still fail later on

as for why I tried to force download it, is because I notice that there's a call to evictUbiquitousItem at here, so it should help remove the local copy

XHMM commented 1 year ago

if we call download on not existed file url and listen to the onProgress, will it fail ?

The expected behavior is it should fail because the file doesn't exist, if not, it's a bug I think.


There is a bad case we should know, when download and open the app for the first time and start reading a file on the icloud, an error message will be reported that the file does not exist, this may caused by the system has not yet initialized the icloud directory for the app. I have encountered similar problems before, but I haven't come up with a good solution yet

williamliangwl commented 1 year ago

sorry for late update, yes we noticed this too. Currently, due to tight timeline, we are working around this by enabling user to retry the download / upload manually if it does happens.

By the way, what do you think if we expose a function, something like removeLocalCache, that calls evictUbiquitousItem to enable user to remove the stale local file, if any?

Because in our weird case above, we are now handling that stale local file by calling download twice, the first one is to remove its local copy, but it will fail due to not being able to find the file to download. The second one is to properly download the file.

XHMM commented 1 year ago

sorry for late update, yes we noticed this too. Currently, due to tight timeline, we are working around this by enabling user to retry the download / upload manually if it does happens.

By the way, what do you think if we expose a function, something like removeLocalCache, that calls evictUbiquitousItem to enable user to remove the stale local file, if any?

Because in our weird case above, we are now handling that stale local file by calling download twice, the first one is to remove its local copy, but it will fail due to not being able to find the file to download. The second one is to properly download the file.

Good suggestion. I will expose this function in the next release. 😄

williamliangwl commented 1 year ago

thank you! 🎉

I will close this issue then