iniciar - Exponer el contenedor ubicuo de una aplicación a iCloud Drive en iOS 8
icloud iniciar sesion (11)
Estoy desarrollando una aplicación habilitada para iCloud donde los usuarios podrán importar y exportar archivos a través de iCloud Drive. Al navegar por iCloud Drive, ya sea utilizando UIDocumentPickerViewController
(iOS 8) o Finder (OS X Yosemite), puedo ver directorios creados / propiedad de otras aplicaciones habilitadas para iCloud Drive, como Automator, Keynote o TextEdit.
Quiero que nuestra aplicación también exponga su directorio de documentos ubicuos en iCloud Drive, pero aún no he podido resolverlo. Dentro de algunos de los archivos Info.plist
de las aplicaciones mencionadas, he descubierto esta clave:
<key>NSUbiquitousContainers</key>
<dict>
<key>com.apple.TextEdit</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
</dict>
</dict>
Estas claves también están documentadas here , pero no he encontrado ninguna otra documentación sobre el tema más amplio. Editar / Nota: Aunque no contiene la respuesta a mis preguntas, la Guía de programación del Selector de documentos es un recurso útil.
He intentado agregar las claves / valores mencionados anteriormente a nuestra aplicación, pero no he visto ningún efecto. Cosas que he notado / intentado:
Para aplicaciones de terceros, los contenedores de iCloud se construyen de esta manera:
iCloud.$(CFBundleIdentifier)
. No estoy seguro de por qué TextEdit solo utiliza el identificador de paquete puro, pero para nuestro identificador, he intentado ambos enfoques, es decir, con y siniCloud.
prefijo. También he reconocido que es necesario codificar el identificador del paquete (es decir, no usariCloud.$(CFBundleIdentifier)
) ya que solo los valores de PLIST parecen resolverse en el momento de la compilación, pero no las claves.Agregué un subdirectorio programáticamente (a
<containerPath>/Documents
) para que el contenedor no esté vacío. Sin embargo, esto no debería importar ya que todos los directorios de las otras aplicaciones estaban inicialmente vacíos, también.Algunas aplicaciones de Apple que aparecen en iCloud Drive no tienen estas entradas en su
Info.plist
, por ejemplo, Números y Páginas.iCloud está configurado correctamente y puedo buscar programáticamente en el contenedor de ubicuidad utilizando la URL que devuelve
[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
.He iniciado sesión en una cuenta de iCloud donde iCloud Drive está habilitado. Puedo ver el contenido de mi unidad iCloud en el
UIDocumentPickerViewController
.Utilizo el simulador iOS 8 beta 5 (y Yosemite beta 5 para ver el directorio de iCloud Drive en la Mac) ( Editar / Nota: Esto también se aplica a la versión beta 6)
Así es como se ve mi archivo de Entitlements (solo partes relevantes)
<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/>
He configurado esto utilizando la interfaz de usuario de Xcode en la sección de Capacidades. No entiendo por qué la última clave no tiene una entrada, pero agregar <string>iCloud.$(CFBundleIdentifier)</string>
no ayuda. En su lugar, hace que Xcode se queje en la interfaz de usuario de capacidades, por lo que lo he eliminado. Edición / Nota: En Xcode beta 6, esto se ha corregido, es decir, el identificador del contenedor de ubicuidad debe configurarse y Xcode puede solucionarlo por usted.
Preguntas originales: Entonces ... ¿es un error? ¿No funciona todavía? ¿Lo estoy haciendo mal? No pude encontrar un problema conocido en las notas de la versión.
Editar:
Dos cosas más que he probado:
Agregar la clave (opcional)
NSUbiquitousContainerName
(valor +) al diccionario específico del contenedor, como lo sugiere Erikmitk.Agregar solo la clave / valor
NSUbiquitousContainerIsDocumentScopePublic
al diccionario raíz PLIST en lugar del diccionario específico del contenedor, como se hace en una de las aplicaciones de ejemplo de WWDC (busque NewBox).
Cuando editó la lista de información, ¿quizás olvidó aumentar el número de versión del paquete? Este es un requisito según la sesión # 234 de WWDC .
Después de pasearme con esto toda la mañana, leer todas las publicaciones, hacer todos los cambios, la clave que finalmente funcionó para mí fue, como dijo Yet Another Code Maker , cambiar la ID del paquete. Creo que una vez que ha creado un contenedor para un paquete, no se puede volver atrás y cambiar su visibilidad para que aparezca en el Finder. Probé todos los diferentes valores de info.plist pero nada funcionó hasta que cambié a un nuevo nombre de paquete y forcé al sistema a crear uno nuevo. Por cierto, no vi esto en ninguna parte, pero el nombre del paquete, el nombre NSUbiquitousContainer y el nombre NSUbiquitousContainerName pueden ser diferentes, que es lo que hice en mi caso. Después de dedicar tanto tiempo a esto, pensé que seguiría adelante y pondría una aplicación de muestra simple en GitHub en caso de que alguien todavía tenga problemas para depurar su carpeta iCloud que aparece en el Finder, puede encontrarla here . Todos los pasos requeridos se describen en el README .
El mismo problema ocurrió con mi aplicación OSX.
Parece que la configuración de NSUbiquitousContainers funciona solo en el momento de la creación de los contenedores de iCloud. Así que lo intenté con el nuevo ID de Apple (para preparar un entorno limpio de iCloud), se vuelve a funcionar.
El problema es llamar a [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
(o con otro identificador de contenedor si no es el predeterminado) al menos una vez (no por lanzamiento, pero presumiblemente por versión, o al cambiar una de las entradas respectivas de PLIST) para inicializar el directorio. Reconozco que este paso debe combinarse con un aumento del número de versión del paquete, como se sugiere en la respuesta del roop.
Observo que mi pregunta puede haber sido confusa a ese respecto, ya que mencioné el hecho de poder ver el directorio de documentos * mediante el uso de la API en cuestión. Sin embargo, eliminé ese código de la aplicación más tarde, tal vez antes de configurar correctamente el resto de la configuración. No voy a escribir directamente en el directorio de documentos, solo a través del Selector de documentos. Por lo tanto, no ha habido ninguna necesidad de obtener la URL.
Si solo necesita un Selector de documentos para leer / almacenar archivos desde / en iCloud Drive u otros directorios de documentos de aplicaciones, no es necesario llamar a URLForUbiquityContainerIdentifier:
Solo si desea que su aplicación tenga su propio contenedor de ubicuidad (y posiblemente la exponga en iCloud Drive y el Selector de documentos), los pasos mencionados en la publicación original y la llamada a URLForUbiquityContainerIdentifier:
son necesarios.
* Al mencionar el directorio de documentos, siempre me refiero al que está en el contenedor de ubicuidad, no al local.
En mi caso (Xcode 7 e iOS 9), lo único que lo hizo funcionar, después de varios intentos, fue usar un nuevo identificador de paquete (no es necesario cambiar el identificador del contenedor en la nube, solo asegúrese de seleccionar el contenedor). desea utilizar en el Centro de Miembros de Apple Developer y especificar en Xcode un contenedor personalizado en lugar del predeterminado).
De hecho, eso significa que la primera vez que ejecute su aplicación, la sección NSUbiquitousContainers de info.plist debe configurarse. Si lo configuras después como un segundo paso, no funcionará ...
Estaba experimentando un problema similar con mi aplicación. Pude hacer este trabajo haciendo lo siguiente:
Agregue la configuración de
NSUbiquitousContainers
a mi archivoInfo.plist
acuerdo con la documentación aquí https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/FileProvider.html . Aquí está el código relevante:<dict> <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>
¡Importante! Luego cambié el valor de cadena
NSUbiquitousContainerSupportedFolderLevels
anterior deAny
aOne
<key>NSUbiquitousContainerSupportedFolderLevels</key> <string>One</string>
A continuación, y por último, tuve que cambiar
CFBundleVersion
a una versión superior. TambiénCFBundleShortVersionString
elCFBundleShortVersionString
a una nueva versión también.
Construido y ejecutado, y después de eso, ¡la carpeta con el icono de mis aplicaciones apareció correctamente en iCloud Drive! ¡Espero que esto ayude!
La entrada .plist en esta https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/FileProvider.html tiene una entrada adicional:
<key>NSUbiquitousContainerName</key>
<string>MyApp</string>
Tal vez el nombre que falta está prohibiendo que aparezca.
No se pudo encontrar ninguna documentación, pero prueba y error, encontré que:
[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:@"com.apple.CloudDocs"];
Le proporciona la URL base para el disco como se ve en el selector. Al usar esta URL base, pude guardar archivos en mi aplicación y verlos en la unidad iCloud dentro de Yosemite.
Editar 14.8.14
He intentado su configuración plist:
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.net.redacted.docTest</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
</dict>
</dict>
En mi pequeña aplicación de prueba desechable "docTest", de hecho expone el directorio de Documentos vacío en Yosemite y en el selector de documentos.
Captura de pantalla http://spring-appstudio.com/picker-view.png
Parece que cambiar la CFBundleVersion
dejará que funcione.
Creo que puedes intentarlo. Conseguí esto de los foros de desarrolladores de Apple .
Espero que este trabajo para usted.
Sé que este es un tema antiguo, pero en caso de que alguien se encuentre con el mismo problema: la única forma de que mi carpeta de Contenedores esté visible en iCloud Drive (después de haber intentado todas las sugerencias anteriores) era que mi aplicación creara un archivo temporal. en la carpeta Documentos. Tan pronto como hice eso, la Carpeta de Contenedores (y el archivo que creé) aparecieron en mi Mac. Si este es realmente el caso de que tengo que crear un archivo para hacer que esta carpeta esté visible, sería un poco molesto porque mi aplicación es de solo lectura (solo lee los archivos agregados por el usuario a la Carpeta de Contenedores). La Carpeta de Contenedores debe estar visible tan pronto como se inicie la aplicación por primera vez. Supongo que tendré que detectar el primer lanzamiento.
Solo quería enfatizar uno de los descubrimientos del OP que lo solucionó para mí:
También he reconocido que es necesario codificar el identificador del paquete (es decir, no usar
iCloud.$(CFBundleIdentifier))
ya que solo los valores de PLIST parecen resolverse en el momento de la compilación, pero no las claves.
Necesitas codificar el ID del paquete. También actualizar la versión.
(No noté esto en la pregunta hasta que revisé todas las respuestas).