我正在开发一个支持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
。
我使用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)。
答案 0 :(得分:14)
我的申请遇到了类似的问题。我能够通过以下方式完成这项工作:
根据此处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>
重要!然后我将上述NSUbiquitousContainerSupportedFolderLevels
字符串值从Any
更改为One
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>One</string>
接下来,最后,我不得不将CFBundleVersion
更改为更高版本。我还将CFBundleShortVersionString
提升到新版本。
构建并运行,之后,带有我的应用程序图标的文件夹在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)
答案 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和文档选择器中的空文档目录。
答案 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的回复中找到了这个提示。