将应用程序无处不在的容器暴露在iOS 8中的iCloud Drive中

时间:2014-08-08 12:36:05

标签: icloud ios8 entitlements icloud-api info-plist

我正在开发一个支持iCloud的应用程序,用户可以通过iCloud Drive导入和导出文件。浏览iCloud Drive时,无论是使用UIDocumentPickerViewController(iOS 8)还是Finder(OS X Yosemite),我都可以看到其他支持iCloud-Drive的应用创建/拥有的目录,例如Automator,Keynote或文本编辑。

我希望我们的应用程序也能在iCloud Drive中公开其无处不在的文档目录,但还未能弄明白。在上述某些应用程序的Info.plist文件中,我发现了这个密钥:

<key>NSUbiquitousContainers</key>
<dict>
    <key>com.apple.TextEdit</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
    </dict>
</dict>

这些密钥也记录在案here,但我没有找到关于更广泛主题的任何其他文档。 修改/注意:虽然它不包含我的问题的答案,但Document Picker Programming Guide是一个有用的资源。

我已尝试将上述键/值添加到我们的应用中,但没有看到任何效果。我注意到/尝试过的事情:

  • 对于第三方应用,iCloud容器以这种方式构建:iCloud.$(CFBundleIdentifier)。我不确定为什么TextEdit只使用纯包标识符,但对于我们的标识符,我尝试了两种方法,即有和没有iCloud.前缀。我还认识到你需要对包标识符进行硬编码(即,不要使用iCloud.$(CFBundleIdentifier)),因为只有PLIST的值似乎在构建时被解析,而不是键。

  • 我已经以编程方式添加了一个子目录(到<containerPath>/Documents),因此容器不为空。但是,这并不重要,因为所有其他应用程序的目录最初都是空的。

  • iCloud Drive中显示的某些Apple应用在Info.plist中没有这些条目,例如,数字和页面。

  • iCloud设置正确,我可以使用[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];返回的网址以编程方式查看ubiquity容器。

  • 我已登录到启用了iCloud Drive的iCloud帐户。我可以在UIDocumentPickerViewController

  • 中看到我的iCloud Drive内容
  • 我使用iOS 8 beta 5模拟器(以及Yosemite beta 5来查看Mac上的iCloud Drive目录)(编辑/注意:这同样适用于测试版6)

这就是我的Entitlements文件的样子(仅限相关部分)

<key>com.apple.developer.icloud-container-identifiers</key>
<array>
    <string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
    <string>CloudDocuments</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array/>

我在功能部分使用Xcode的UI进行了设置。我不明白为什么最后一个键没有条目,但添加<string>iCloud.$(CFBundleIdentifier)</string>没有帮助。相反,它使Xcode在Capabilities UI中抱怨,所以我删除了它。 编辑/注意:在Xcode beta 6中,这已经修复,即需要设置普遍存储容器标识符,Xcode可以为您解决这个问题。

原始问题:所以......这是一个错误吗?它不起作用吗?我做错了吗?我在发行说明中找不到已知问题。

修改

我尝试了两件事:

  • 按照Erikmitk的建议,将(可选)NSUbiquitousContainerName键(+值)添加到特定于容器的字典中。

  • 仅将NSUbiquitousContainerIsDocumentScopePublic键/值添加到PLIST根词典而不是容器特定的词典,因为它是在WWDC sample apps之一中完成的(查找NewBox)。

12 个答案:

答案 0 :(得分:14)

我的申请遇到了类似的问题。我能够通过以下方式完成这项工作:

  1. 根据此处https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/FileProvider.html的文档,将NSUbiquitousContainers设置添加到我的Info.plist文件中。以下是相关代码:

    <dict>
        <!-- ... other top-level Info.plist settings ... -->
        <key>NSUbiquitousContainers</key>
        <dict>
            <key>iCloud.com.example.MyApp</key>
            <dict>
                <key>NSUbiquitousContainerIsDocumentScopePublic</key>
                <true/>
                <key>NSUbiquitousContainerSupportedFolderLevels</key>
                <string>Any</string>
                <key>NSUbiquitousContainerName</key>
                <string>MyApp</string>
            </dict>
        </dict>
    </dict>
    
  2. 重要!然后我将上述NSUbiquitousContainerSupportedFolderLevels字符串值从Any更改为One

    <key>NSUbiquitousContainerSupportedFolderLevels</key>
    <string>One</string>
    
  3. 接下来,最后,我不得不将CFBundleVersion更改为更高版本。我还将CFBundleShortVersionString提升到新版本。

  4. 构建并运行,之后,带有我的应用程序图标的文件夹在iCloud Drive中正常显示!希望这有帮助!

答案 1 :(得分:13)

当您编辑Info.plist时,您可能忘了提高捆绑版本号?这是WWDC session #234的要求。

答案 2 :(得分:7)

捕获的是调用[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];(或使用另一个容器标识符,如果它不是默认容器标识符)至少一次(不是每次启动,但可能是每个版本,或更改其中一个相应的PLIST条目)为了初始化目录。我认为这一步需要与捆绑版本号的增加相结合,如roop的回答所示。

我注意到我的问题可能在这方面令人困惑,因为我提到能够使用相关API以编程方式查看文档目录。但是,我稍后从应用程序中删除了该代码,可能在正确设置其余部分之前。我不打算直接写入文档目录,只能通过文档选择器。因此,没有必要获取URL。

如果您只需要一个文件选择器来从/在iCloud Drive或其他应用程序的文档目录中读取/存储文件,则无需拨打URLForUbiquityContainerIdentifier:。只有当您希望您的应用程序拥有自己的普遍容器(并可能在iCloud Drive和文档选择器中公开)时,原始帖子中提到的步骤和对URLForUbiquityContainerIdentifier:的调用才是必要的。

*当提到文件目录时,我总是指的是普遍容器中的那个,而不是本地容器。

答案 3 :(得分:3)

看来,更改CFBundleVersion会让它发挥作用。

我想你可以尝试一下。我是从Apple Developer Forums得到的。

希望这对你有用。

答案 4 :(得分:2)

在我的情况下(Xcode 7和iOS 9),在多次尝试之后,唯一使其工作的是使用新的包标识符(您不必更改云容器标识符,只需确保选择要在Apple Developer Member Center中使用的容器,并在Xcode中指定自定义容器而不是默认容器。

实际上,这意味着第一次运行应用程序时,必须设置info.plist的NSUbiquitousContainers部分。如果你之后作为第二步设置它,它将无法工作......

答案 5 :(得分:2)

在整个上午彻夜难忘,阅读所有帖子,进行所有更改后,最终对我有用的关键是, Yet Another Code Maker 声明,更改了套件ID。我认为一旦它为一个包创建了一个容器,你就不能回过头来改变它的可见性,让它出现在Finder中。我曾尝试过所有不同的info.plist值,但在我更改为新的捆绑包名称并强制系统创建新的捆绑名称之前,没有任何工作。顺便说一下,除了包名,NSUbiquitousContainer名和NSUbiquitousContainerName都可以有所不同之外,我没有看到这一点,这就是我在我的案例中所做的。在花了这么多时间之后,我想我会继续在GitHub上放一个简单的示例应用,以防任何人在Finder中调试他们的iCloud文件夹时仍然遇到问题 - 你可以找到它here。所有必需的步骤都在README中列出。

答案 6 :(得分:1)

无法找到任何文档,但是反复试验,我发现:

[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:@"com.apple.CloudDocs"]; 

为您提供驱动器的基本URL,如选择器中所示。使用此基本URL,我能够在我的应用程序中保存文件,并在Yosemite内的iCloud驱动器上查看。

编辑14.8.14

我尝试了你的plist设置:

<key>NSUbiquitousContainers</key>
<dict>
    <key>iCloud.net.redacted.docTest</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
    </dict>
</dict>

在我的小一次性测试应用程序“docTest”中,它确实暴露了Yosemite和文档选择器中的空文档目录。

屏幕截图http://spring-appstudio.com/picker-view.png

答案 7 :(得分:0)

documentation page上的.plist条目还有一个条目:

<key>NSUbiquitousContainerName</key>
<string>MyApp</string>

也许缺少的名字禁止它出现。

答案 8 :(得分:0)

我的OSX应用程序出现同样的问题。

似乎NSUbiquitousContainers设置仅适用于iCloud容器的创建时间。所以我尝试使用新的Apple ID(用于准备干净的iCloud环境),它开始工作。

答案 9 :(得分:0)

只是想强调一下OP为我修复它的发现:

  

我还认识到你需要对包标识符进行硬编码(即,不要使用iCloud.$(CFBundleIdentifier)),因为只有PLIST的值似乎在构建时被解析,而不是键。

您需要对包ID进行硬编码。还要更新版本。

(在我完成所有答案之前,我没有注意到这个问题。)

答案 10 :(得分:0)

我知道这是一个旧线程,但万一有人遇到同样的问题:只有我让我的Container文件夹在iCloud Drive中可见(在尝试了所有上述建议之后)才能让我的应用创建Documents文件夹中的临时文件。一旦我这样做,容器文件夹(和我创建的文件)出现在我的Mac上。如果我真的需要创建一个文件来使这个文件夹可见,那么这会有点烦人,因为我的应用程序是一个只读应用程序(只读取用户添加到容器文件夹的文件)。第一次启动应用程序时,容器文件夹需要立即可见。我想我必须检测第一次发射。

答案 11 :(得分:0)

好吧,它在任何地方都没有记录,而是尝试在容器中添加Documents文件夹并将文件存储在该文件夹中。

this Apple Developer Forum thread的回复中找到了这个提示。