将文档文件写入/保存/移动到iCloud驱动器的Swift方法

21
我已经尝试了两天以上将文件写入iCloud驱动器。我尝试过直接编写简单文本文件,然后将其移动到本地,使用UIDocumentMenuViewController等方法。我的代码没有出现任何错误,并且在调试器中步进时看起来是成功的,但是当我检查文件是否存在或至少iCloud目录是否存在时,没有找到任何内容。我在模拟器和iPhone上都尝试过,触发了iCloud同步以及我能想到的其他所有的方法。
我的主要目标是将一个文本文件简单地写入iCloud驱动器,稍后它将成为"numbers"文件。
我已经设置了plist文件和我的entitlements:
<key>NSUbiquitousContainers</key>
<dict>
    <key>iCloud.com.paul.c.$(PRODUCT_NAME:rfc1034identifier)</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerName</key>
        <string>myCloudTest</string>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
    </dict>
</dict>

我已按照以下链接所述,提升了我的捆绑版本号: 将iOS 8文档保存到iCloud Drive 我尝试了数十个教程,但没有成功。 我最新的代码是基于这个示例构建的:https://medium.com/ios-os-x-development/icloud-drive-documents-1a46b5706fe1 以下是我的代码:
@IBAction func ExportFile(sender: AnyObject) {

    var error:NSError?

    let iCloudDocumentsURL = NSFileManager.defaultManager().URLForUbiquityContainerIdentifier(nil)?.URLByAppendingPathComponent("myCloudTest")

    //is iCloud working?
    if  iCloudDocumentsURL != nil {

        //Create the Directory if it doesn't exist
        if (!NSFileManager.defaultManager().fileExistsAtPath(iCloudDocumentsURL!.path!, isDirectory: nil)) {
                //This gets skipped after initial run saying directory exists, but still don't see it on iCloud
                NSFileManager.defaultManager().createDirectoryAtURL(iCloudDocumentsURL!, withIntermediateDirectories: true, attributes: nil, error: nil)
        }
    } else {
        println("iCloud is NOT working!")
        //  return
    }

    if ((error) != nil) {
        println("Error creating iCloud DIR")
    }


    //Set up directorys
    let localDocumentsURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: .UserDomainMask).last as! NSURL

    //Add txt file to my local folder
    let myTextString = NSString(string: "HELLO WORLD")
    let myLocalFile = localDocumentsURL.URLByAppendingPathComponent("myTextFile.txt")
    let written = myTextString.writeToURL(myLocalFile, atomically: true, encoding: NSUTF8StringEncoding, error: &error)

    if ((error) != nil){
        println("Error saving to local DIR")
    }


   //If file exists on iCloud remove it
    var isDir:ObjCBool = false
    if (NSFileManager.defaultManager().fileExistsAtPath(iCloudDocumentsURL!.path!, isDirectory: &isDir)) {
        NSFileManager.defaultManager().removeItemAtURL(iCloudDocumentsURL!, error: &error)
    }

    //copy from my local to iCloud
    if (error == nil && !NSFileManager.defaultManager().copyItemAtURL(localDocumentsURL, toURL: iCloudDocumentsURL!, error: &error)) {
        println(error?.localizedDescription);
    }

感谢您抽出时间来阅读。

祝愉快, 保罗

我在上述代码后在我的iPhone上运行了一些代码:

var error:NSError?
    let iCloudDocumentsURL = NSFileManager.defaultManager().URLForUbiquityContainerIdentifier(nil) //?.URLByAppendingPathComponent("myCloudTest")

    var fileManager: NSFileManager = NSFileManager()


    var fileList: NSArray = fileManager.contentsOfDirectoryAtURL(iCloudDocumentsURL!, includingPropertiesForKeys: nil, options: nil, error: &error)!
    var filesStr: NSMutableString = NSMutableString(string: "Files in iCloud folder \n")
    for s in fileList {

        println(s)
    }

它打印出了我的文本文件的路径:file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~paul~c~myApp/MyTextFile.txt

我的文件在那里,我只是在iCloud驱动器上看不到它。


你解决了这个问题吗?我也遇到了同样的问题,尝试了这里所有值得尝试的建议都没有成功。如果你已经解决了这个问题,请在这里回答自己的问题,让我们知道。 - RawMean
想问一下,你有没有机会将这段代码迁移到Swift 3?谢谢! - Kaiusee
5个回答

6
我遇到了这个问题。我按照这里的建议,发现我的Info.plist键不正确。一旦我将其更改为iCloud.MY_BUNDLE_IDENTIFIER(即从Info.plist中较高的CFBundleIdentifier键中复制字符串),它就开始正常工作了。
从您的键中删除“.com”可能会解决您的问题。

对我而言,我有一个问题,即在开发者门户网站上注册的iCloud容器与在App Store Connect注册的应用程序包标识符大小写不同。我必须更改info.plist中NSUbiquitousContainers下的iCloud.$(PRODUCT_BUNDLE_IDENTIFIER),以匹配iCloud容器的大小写(iCloud.com.company.appname - > iCloud.com.company.AppName)。还要确保资格证书中“普及性容器标识符”下的ID匹配大小写。并且增加构建号码(和版本号码?)以查看文件应用程序中的更改更新。 - Thompsonmachine

4

FWIW:

我还发现,在 bundle ID 中的项目名称很重要。

我的项目 bundle ID 大致如下:aaa-bbb-ccc-ddd

我无法让 iCloud 正常工作。

然后,我将其重命名为:aaa-bbb.ccc-ddd

它开始正常工作了。


1

你需要做两件事情:

  1. 按照@rick Andrews所说的做:“一旦我将其更改为iCloud.MY_BUNDLE_IDENTIFIER(即从Info.plist中更高级别的CFBundleIdentifier键复制字符串)”
  2. 将您的文件存储在容器的子文件夹Documents中
struct iCloudStore {
    public var containerUrl: URL! {
        return fileManager.url(forUbiquityContainerIdentifier: nil)!
    }
    
    public var documents: URL! {
        return containerUrl.appendingPathComponent("Documents", isDirectory: true)
    }
    
    private let fileManager: FileManager = FileManager.default

    func store(url: URL) {
      // move ulr into the documents folder as a file
 let fileID = "\(UUID().uuidString).<#extension#>"
        let icloudFile = documents.appendingPathComponent(fileID, isDirectory: false)
        try fileManager.copyItem(at: url, to: icloudFile)
    }
}

1
我相信我已经找到了一种方法,可以在不不断“推”我的捆绑编号的情况下,使所有内容重新同步。在更改“能力”区域的键值存储/iCloud文档/CloudKit时,我尝试过多次,并且似乎每次都有效。
  1. 在您的Mac上退出iCloud
  2. 在模拟器上退出iCloud
  3. 重新登录您的Mac上的iCloud
  4. 在模拟器上重新登录iCloud
  5. 从XCode进行干净的构建(Shift-Cmd-K)
这似乎会重置文件夹结构的同步,当您的应用程序写入iCloud文档目录时-而无需触摸捆绑编号。它需要一点时间来完成,但我有点强迫症,而且比较喜欢我的初始应用程序启动从1开始!

0

或许有一个容器名称的规则。
我尝试了以下名称。

○:iSheet
×:sheetFiles
×:com.myname.sheetFiles


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接