objective c - Sandbox de aplicaciones: el marcador del documento no se resuelve; no devolver ningún error
objective-c macos (1)
En su código Gist, cambie la siguiente línea en AppDelegate.m (línea 61):
[xmlTextFileData writeToURL:savePanel.URL atomically:YES];
a
[xmlTextFileData writeToURL:savePanel.URL atomically:NO];
Tu código funcionará.
La razón de esto es probablemente la misma razón por la cual es necesario tener un archivo existente (pero vacío) que contendrá los marcadores del alcance del documento antes de llamar [anURL bookmarkDataWithOptions]: Al crear la instancia de NSData, el ScopedBookmarkAgent agrega algo (como una etiqueta, probablemente un atributo de archivo extendido) a ese archivo.
Si escribe datos (es decir, las URL de los marcadores) en ese archivo de forma atómica, de hecho, no se escriben directamente en el archivo sino primero en un archivo temporal cuyo nombre se cambia si la operación de escritura fue exitosa. Parece que la etiqueta que se ha agregado al archivo (vacío, pero existente) que contendrá los marcadores se está perdiendo durante este proceso de escritura en un archivo temporal y luego cambiarle el nombre (y, por lo tanto, eliminar el archivo original, vacío) .
Por cierto: no debería ser necesario crear marcadores de ámbito de aplicación antes de pasar las URL respectivas al archivo xml que contiene los marcadores de ámbito de documento.
Adición: com.apple.security.files.bookmarks.collection-scope ha cambiado su nombre a com.apple.security.files.bookmarks.document-scope en 10.7.4.
Estoy protegiendo mi aplicación y tratando de permitir la importación / exportación de varios archivos, utilizando un archivo XML para referirme a ellos. Para permitir que mi aplicación (u otra aplicación de espacio aislado) acceda a los archivos enumerados en el XML, también estoy incluyendo un marcador de seguridad serializado. Lo estoy serializando como se describe en esta respuesta , y mis pruebas de unidad (que no están en un espacio aislado) escriben y leen los datos XML sin problemas. Cuando mi aplicación resuelve el marcador, el NSURL
devuelto es nulo, al igual que la referencia NSError
. Como no creo que ese sea el caso, ¿por qué está sucediendo? Puedo NSOpenPanel
al usuario que seleccione un archivo / directorio con un NSOpenPanel
, pero todavía me gustaría que los marcadores funcionen como deberían.
Reproducido en un proyecto de prueba
Para reproducir en casa, cree una nueva aplicación Cocoa en Xcode y use la siguiente Gist para los archivos del proyecto: https://gist.github.com/2582589 ( actualizado con un bucle apropiado para la próxima vista )
Luego, siga las instrucciones de Apple para firmar el proyecto de código. Reproduce el problema (que rdar://11369377 a Apple como rdar://11369377 ) haciendo clic en los botones en secuencia. Selecciona cualquier archivo en el disco (fuera del contenedor de la aplicación), luego un XML para exportar y luego el mismo XML para importar.
Espero que ustedes puedan ayudarme a descubrir qué estoy haciendo mal. O estoy haciendo algo mal y el marco se está manteniendo erróneamente a sí mismo, o lo estoy haciendo bien y está totalmente roto. Intento no culpar al marco , así que ¿cuál es? ¿O hay otra posibilidad?
Código de muestra
Exportando el XML a docURL
:
// After the user picks an XML (docURL) destination with NSSavePanel
[targetURL startAccessingSecurityScopedResource];
NSData *bookmark = [targetURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:docURL
error:&error];
[targetURL stopAccessingSecurityScopedResource];
Importando el XML desde docURL
:
// After the user selected the XML (docURL) from an NSOpenPanel
NSURL *result = [NSURL URLByResolvingBookmarkData:bookmarkData
options:NSURLBookmarkResolutionWithSecurityScope
relativeToURL:docURL
bookmarkDataIsStale:nil
error:&error];
Intenté rodear esta llamada con [docURL ..AccessingSecurityScopedResource]
, lo que no hizo una diferencia (como se esperaba, ya que docURL ya está dentro del alcance después de haber sido seleccionado en el Panel Abierto
Además, especifico lo siguiente en mi archivo app.entitlements
:
com.apple.security.files.user-selected.read-write
com.apple.security.files.bookmarks.app-scope
com.apple.security.files.bookmarks.collection-scope
Como se mencionó anteriormente, el segundo paso (resolver el marcador) se completa, pero deja el error
y el result
nulos. Como he estado implementando el sandboxing, la mayoría de los errores que he cometido han dado lugar a la NSError
un NSError
, lo que me ayudó a resolver el error. Pero ahora no hay ningún error, y no se resuelve ninguna URL.
Varios pasos para solucionar problemas
Intenté colocar el archivo XML en la zona de pruebas de mi aplicación, lo que no marcó ninguna diferencia, por lo que el problema no es el acceso al archivo XML.
La aplicación utiliza ARC, pero también las pruebas de unidad, que tienen éxito. También intenté usar un método alloc / init en lugar del método de clase lanzado automáticamente (por si acaso)
Pegué el código de resolución de la URL inmediatamente después de crear el marcador, y se ejecuta correctamente, produciendo una URL de ámbito de seguridad
Hice un
po
en el marcador creado originalmente (antes de la serialización), y luego en el marcador después de la deserialización, y coinciden al 100%. La serialización no es el problemaCFURLCreateByResolvingBookmarkData(..)
llamada de resolución conCFURLCreateByResolvingBookmarkData(..)
, sin cambios. Si se trata de un error, está presente en la API de Core Foundation y en la capa Cocoa.Especificar un valor para
bookmarkDataIsStale:
no tiene ningún efectoSi especifico
0
para lasoptions:
obtengo un NSURL válido, pero no tiene un alcance de seguridad y, por lo tanto, las llamadas subsiguientes para leer el archivo siguen fallandoEn otras palabras, el marcador deserializado parece ser válido. Si los datos de los marcadores estuvieran dañados, dudo que NSURL pueda hacer algo con ellos
NSURL.h
no contenía ningún comentario útil para señalar algo que estoy haciendo mal
¿Alguien más está utilizando con éxito los marcadores de documentos de ámbito de seguridad en una aplicación de espacio aislado? Si es así, ¿qué estás haciendo diferente a mí?
Solicitud de versión del SO
¿Puede alguien con acceso a la versión beta de Mountain Lion verificar si mi proyecto de muestra muestra o no el mismo error (falta de)? Si es un error que se ha corregido después de Lion, no me preocuparé por eso. Todavía no estoy en el programa de desarrolladores y, por lo tanto, no tengo acceso. No estoy seguro si responder a esa pregunta violaría la NDA, pero espero que no.