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).
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.