John Raptis
John Raptis

Reputation: 197

App's created Folders/Files don't show up in "Files" on iPhone

wonder if anyone can help me. I have an app and I'm trying to move some files into iCloud so they'll show up in "Files" and cloud to other devices. I've been going through lots of resources online researching what's wrong, and nothing seems to help.

In my app project, I have turned on iCloud Documents in capabilities.

In my plist file, I have this:

<key>NSUbiquitousContainers</key>
    <dict>
        <key>iCloud.com.mypublishername.myappname</key>
        <dict>
            <key>NSUbiquitousContainerIsDocumentScopePublic</key>
            <true/>
            <key>NSUbiquitousContainerName</key>
            <string>myappname</string>
            <key>NSUbiquitousContainerSupportedFolderLevels</key>
            <string>Any</string>
        </dict>
    </dict>

In my entitlements file I have:

<dict>
    <key>com.apple.developer.icloud-container-identifiers</key>
    <array>
        <string>iCloud.com.mypublishername.myappname</string>
    </array>
    <key>com.apple.developer.icloud-services</key>
    <array>
        <string>CloudDocuments</string>
    </array>
    <key>com.apple.developer.ubiquity-container-identifiers</key>
    <array>
        <string>iCloud.com.mypublishername.myappname</string>
    </array>
</dict>

in ObjC, I'm fetching the iCloud folder like so:

NSURL *rootDirectory = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]URLByAppendingPathComponent:@"Documents"];
if (rootDirectory)
{
    if (![[NSFileManager defaultManager] fileExistsAtPath:rootDirectory.path isDirectory:nil]) [[NSFileManager defaultManager] createDirectoryAtURL:rootDirectory withIntermediateDirectories:YES attributes:nil error:nil];
    gCloudFolder=rootDirectory;
}

Then, when I save a file, I do so locally, and move it into the cloud folder like this:

//
// theFilename is a file in the app's documents folder...
//
int aFile=creat(theFilename,S_IREAD|S_IWRITE);close(aFile);
aFile=open(theFilename,O_BINARY|O_RDWR);
if (aFile)
{
    write(aFile,theDataPtr,theLen);
    close(aFile);

    if (gCloudFolder)
    {
        NSURL *aLocalStr=[NSURL fileURLWithPath:[NSString stringWithUTF8String:theFilename]];
        NSURL *aCloudStr=[gCloudFolder URLByAppendingPathComponent:@"testing_file.txt"];
                
        NSError *error;
        if (![[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:aLocalStr destinationURL:aCloudStr error:&error]) NSLog(@"iCloud Error occurred: %@", error);
    }

So... what happens. This file DOES get created. If I run this twice, it tells me it can't move to testing_file.txt because it already exists. Also, if I try to setUbiquitous:NO on the file, it tells me I can't set it to no when the file hasn't been synced.

Any idea why my app's folder and this file don't show up in my FILES folder under iCloud?

I have increased the bundle version, which is something I've seen elsewhere. Did nothing.

What am I doing wrong?

Upvotes: 3

Views: 652

Answers (1)

matt
matt

Reputation: 534977

This completely stunned me; I had no idea it was possible. I'll just describe my test app in full. It's going to look a lot like yours!

Here is the bundle identifier:

enter image description here

Here is the entitlement:

enter image description here

Here is the entitlement text:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.icloud-container-identifiers</key>
    <array>
        <string>iCloud.com.neuburg.matt.SaveIntoFilesApp</string>
    </array>
    <key>com.apple.developer.icloud-services</key>
    <array>
        <string>CloudDocuments</string>
    </array>
    <key>com.apple.developer.ubiquity-container-identifiers</key>
    <array>
        <string>iCloud.com.neuburg.matt.SaveIntoFilesApp</string>
    </array>
</dict>
</plist>

Here is the entry in the Info.plist:

<key>NSUbiquitousContainers</key>
<dict>
    <key>iCloud.com.neuburg.matt.SaveIntoFilesApp</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerName</key>
        <string>MyApp</string>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
    </dict>
</dict>

Here is the app delegate:

var ubiq : URL!

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    DispatchQueue.global(qos:.default).async {
        let fm = FileManager.default
        let ubiq = fm.url(forUbiquityContainerIdentifier:nil)
        print("ubiq: \(ubiq as Any)")
        DispatchQueue.main.async {
            self.ubiq = ubiq
        }
    }

    return true
}

Here is the button I tap:

@IBAction func doButton (_ sender:Any) {
    if let del = UIApplication.shared.delegate as? AppDelegate {
        if let ubiq = del.ubiq {
            do {
                let fm = FileManager.default
                let docs = ubiq.appendingPathComponent("Documents")
                try? fm.createDirectory(at: docs, withIntermediateDirectories: false, attributes: nil)
                let url = docs.appendingPathComponent("test.txt")
                print("here we go")
                try? fm.removeItem(at: url)
                try "howdy \(Date())".write(to: url, atomically: true, encoding: .utf8)
                print("saved")
                
            } catch {
                print(error)
            }
        }
    }
}

I did have to increment the bundle version (from 1 to 2) and I did have to kill and restart the Files app. And then I saw my file (and can open and examine it):

enter image description here

Upvotes: 2

Related Questions