Launching iOS app from iCloud Drive

My iOS app supports a document type and includes the appropriate UTI data. It can therefore open documents of a specific type from mail attachments, for instance. It works well.


I am currently stumped, however: when I open a document from the iCloud Drive app (tap document, share button, "Copy to <app>") my application gets launched but any attempts to copy the item from the provided URL fails with NSCocoaErrorDomain, error 257 (basically telling me I don't have the permissions to read the file). This issue is not present when my app is running in the background, however, and does not seem to occur when the app gets launched from a mail attachment (whether it's running ot not).


I compared the URLs handed to my app and they are identical, whether the app was running or not.


Here's the URL my app is handed: "file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/filename.ext"


The code I'm using is the following:

// uniqueURL is a destination URL in my app's sandbox:
// file:///var/mobile/Containers/Data/Application/12AB2BA0-EA63-4FAC-A7D8-779964868B06/Documents/filename.ext

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
     let fileCoordinator = NSFileCoordinator(filePresenter: nil)
     fileCoordinator.coordinateReadingItemAtURL(url, options: .WithoutChanges, error: nil) { newURL in
     do {
          try NSFileManager.defaultManager().copyItemAtURL(newURL, toURL: uniqueURL)
     } catch {
          print("Error!") // this is where I'm getting NSCocoaErrorDomain:257
     }
}


This issue seems to be identical to that other thread:

https://forums.developer.apple.com/message/29985#29985


However, I'm not running on a beta OS. My device is an iPhone 6s running iOS 9.3.2 (13F69).

Accepted Reply

Actually, I'm a little puzzled as the issue only occurs when I do the processing from application:didFinishLaunchingWithOptions.


I was doing the following:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {     
     // ...
     if let url = launchOptions?[UIApplicationLaunchOptionsURLKey] as? NSURL {
          processURL(url)
          return false
     }
     return true
}


While I had the following:

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
     processURL(url)
     return true
}


If I comment out lines 3-6 in didFinishLaunchingWithOptions, everything works again. This is somewhat puzzling.


From the API doc:

Your implementation of this method should open the specified URL and update its user interface accordingly. If your app had to be launched to open the URL, the app calls the

application:willFinishLaunchingWithOptions:
and
application:didFinishLaunchingWithOptions:
methods first, followed by this method. The return values of those methods can be used to prevent this method from being called. (If the app is already running, only this method is called.)


It's as if it's too early in the app launching process for me to copy the file (If I attempt to do it from didFinishLaunchingWithOptions).


I'll mark this as answered but I'm still puzzled.

Replies

Actually, I'm a little puzzled as the issue only occurs when I do the processing from application:didFinishLaunchingWithOptions.


I was doing the following:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {     
     // ...
     if let url = launchOptions?[UIApplicationLaunchOptionsURLKey] as? NSURL {
          processURL(url)
          return false
     }
     return true
}


While I had the following:

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
     processURL(url)
     return true
}


If I comment out lines 3-6 in didFinishLaunchingWithOptions, everything works again. This is somewhat puzzling.


From the API doc:

Your implementation of this method should open the specified URL and update its user interface accordingly. If your app had to be launched to open the URL, the app calls the

application:willFinishLaunchingWithOptions:
and
application:didFinishLaunchingWithOptions:
methods first, followed by this method. The return values of those methods can be used to prevent this method from being called. (If the app is already running, only this method is called.)


It's as if it's too early in the app launching process for me to copy the file (If I attempt to do it from didFinishLaunchingWithOptions).


I'll mark this as answered but I'm still puzzled.

I'm seeing the same thing in iOS 10.1. It's just as you described.


I also tried commenting out the processURL() from application:didFinishLaunchingWithOptions, allowing the flow to pass to application:openURL:sourceApplication:annotation. And that does help sometimes, but not consistently. I still get an error when trying to move or copy the file at the URL that is passed to the application on occasion.


As in your case, this only happens when opening from the iCloud Drive app. Opening from other apps works just fine.


It does feel like a timing issue, as if the file isn't quite ready for the app to process. So I added a 2 second delay inside application:openURL:sourceApplication:annotation before trying to move or copy the incoming URL, but unfortunately that does not help.


I'm stumped. This seems like a basic flow that should work like any other "open in" use case.

I think I figured out why this failed on occasion for me. It's when the iCloud Drive app hasn't yet downloaded the file but it's passing it to the app anyway. I don't know why iCloud Drive would do that, but that seems to be the only case that's failing.

I have the same issue on iOS 12.3.1.

It only occurs when I have "Supports opening documents in place" set to YES in the Info.plist file. If YES, then the url points to the file in iCloud, for which the app has no permissions. If NO, then iOS makes a copy of the file in the Application Sandbox, and it can be opened without problems.


Did you ever find a solution to the problem?

I encountered a similar issue on iOS 12 where NSData dataWithContentsOfURL: was returning nil for iCloud urls. Wrapping the call in between

[nsUrl startAccessingSecurityScopedResource] and [nsUrl stopAccessingSecurityScopedResource] worked for me to read the file (with "Supports opening documents in place" set to YES)
. (Our app makes a local copy for read-only files before writing any changes.) From https://stackoverflow.com/questions/47430244/copy-file-from-ios-11-files-app-to-sandbox

Lol

Lo

Dgjjhg

..

Wja8w

desde el simulador de xcode sube un archivo a firebase pero desde my iphome no. este es el error que sale File at URL: file:///private/var/mobile/Library/Mobile%20Documents/comappleCloudDocs/Downloads/am401s02.pdf is not reachable. Ensure file URL is not a directory, symbolic link, or invalid url.