¿Cómo asocio tipos de archivos con una aplicación de iPhone?

318

Sobre el tema de asociar su aplicación de iPhone con tipos de archivos.

En esta pregunta informativa, aprendí que las aplicaciones podrían asociarse con protocolos de URL personalizados.

Eso fue hace casi un año y desde entonces Apple introdujo el "Soporte de documentos", que va un paso más allá y permite que las aplicaciones se asocien con los tipos de archivos. Se habla mucho en la documentación sobre cómo configurar su aplicación para iniciar otras aplicaciones apropiadas cuando encuentra un tipo de archivo desconocido. Esto significa que la asociación no funciona de forma predeterminada para ninguna aplicación, como lo hizo el protocolo de registro URL.

Esto me lleva a la pregunta: ¿las aplicaciones del sistema como Safari o Mail implementaron este sistema para elegir aplicaciones asociadas, o no harán nada, como antes?

Mihai Damian
fuente

Respuestas:

408

El manejo del tipo de archivo es nuevo con iPhone OS 3.2, y es diferente de los esquemas de URL personalizados ya existentes. Puede registrar su aplicación para manejar tipos de documentos particulares, y cualquier aplicación que use un controlador de documentos puede transferir el procesamiento de estos documentos a su propia aplicación.

Por ejemplo, mi aplicación Molecules (para la cual está disponible el código fuente) maneja los tipos de archivo .pdb y .pdb.gz, si se reciben por correo electrónico o en otra aplicación compatible.

Para registrar el soporte, necesitará tener algo como lo siguiente en su Info.plist:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array>
            <string>Document-molecules-320.png</string>
            <string>Document-molecules-64.png</string>
        </array>
        <key>CFBundleTypeName</key>
        <string>Molecules Structure File</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.sunsetlakesoftware.molecules.pdb</string>
            <string>org.gnu.gnu-zip-archive</string>
        </array>
    </dict>
</array>

Se proporcionan dos imágenes que se utilizarán como iconos para los tipos admitidos en Mail y otras aplicaciones capaces de mostrar documentos. La LSItemContentTypesclave le permite proporcionar una variedad de identificadores de tipo uniforme (UTI) que su aplicación puede abrir. Para obtener una lista de las IU definidas por el sistema, consulte la Referencia de identificadores de tipo uniforme de Apple . Puede encontrar aún más detalles sobre las infecciones urinarias en la Descripción general de los identificadores de tipo uniforme de Apple . Esas guías residen en el centro de desarrolladores de Mac, porque esta capacidad se ha trasladado desde Mac.

Una de las infecciones urinarias utilizadas en el ejemplo anterior estaba definida por el sistema, pero la otra era una infección urinaria específica de la aplicación. La UTI específica de la aplicación deberá exportarse para que otras aplicaciones del sistema puedan conocerla. Para hacer esto, debe agregar una sección a su lista de información como la siguiente:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.plain-text</string>
            <string>public.text</string>
        </array>
        <key>UTTypeDescription</key>
        <string>Molecules Structure File</string>
        <key>UTTypeIdentifier</key>
        <string>com.sunsetlakesoftware.molecules.pdb</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pdb</string>
            <key>public.mime-type</key>
            <string>chemical/x-pdb</string>
        </dict>
    </dict>
</array>

Este ejemplo particular exporta la com.sunsetlakesoftware.molecules.pdbUTI con la extensión de archivo .pdb, correspondiente al tipo MIME chemical/x-pdb.

Con esto en su lugar, su aplicación podrá manejar documentos adjuntos a correos electrónicos o desde otras aplicaciones en el sistema. En Correo, puede tocar y mantener presionado para que aparezca una lista de aplicaciones que pueden abrir un archivo adjunto en particular.

Cuando se abra el archivo adjunto, su aplicación se iniciará y deberá manejar el procesamiento de este archivo en el -application:didFinishLaunchingWithOptions:método de delegado de su aplicación. Parece que los archivos cargados de esta manera desde Mail se copian en el directorio Documentos de su aplicación en un subdirectorio correspondiente a la casilla de correo electrónico a la que llegaron. Puede obtener la URL de este archivo dentro del método de delegado de la aplicación usando un código como el siguiente:

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];

Tenga en cuenta que este es el mismo enfoque que utilizamos para manejar esquemas de URL personalizados. Puede separar las URL de archivo de otras utilizando código como el siguiente:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}
Brad Larson
fuente
99
Cabe señalar que -application:didFinishLaunchingWithOptions:en la aplicación, solo se llama al delegado si su aplicación no está en segundo plano cuando se abre para manejar un archivo.
memmons
3
Evitar QuickLook: raywenderlich.com/1980/…
TheLearner
44
Deberíamos usar - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urltambién en iOS 4+
Dmitry
1
¿Qué pasa con la clave 'CFBundleTypeExtensions'? Su fragmento no parece establecerlo. ¿No es necesario?
Bram
3
He probado toda la metodología proporcionada aquí y en otros lugares también, pero todavía estoy luchando por abrir archivos PNG. Estoy trabajando con iOS 7. En algunos lugares dicen que este problema comienza con iOS 6. ¿Es cierto? ¿No podemos abrir archivos png en el cuadro de diálogo "Abrir en" con ios 7?
Kumar Aditya
24

Además de la excelente respuesta de Brad, descubrí que (al menos en iOS 4.2.1) al abrir archivos personalizados desde la aplicación Correo, su aplicación no se activa ni se notifica si el archivo adjunto se ha abierto antes. Aparece la ventana emergente "abrir con ...", pero no hace nada.

Esto parece solucionarse al (re) mover el archivo desde el directorio de la Bandeja de entrada. Un enfoque seguro parece ser tanto (re) mover el archivo a medida que se abre (en -(BOOL)application:openURL:sourceApplication:annotation:) como ir a través del directorio Documentos / Bandeja de entrada, eliminando todos los elementos, por ejemplo, en applicationDidBecomeActive:. Es posible que se necesite la última captura general para que la aplicación vuelva a estar limpia, en caso de que una importación anterior cause un bloqueo o se interrumpa.

mvds
fuente
66
No veo este comportamiento. Si mi aplicación está en segundo plano, -(BOOL)application:openURL:sourceApplication:annotation:siempre se llama, incluso para los archivos adjuntos que ya se han abierto. Cada vez que se abre el archivo adjunto, se agrega un número al sufijo del nombre del archivo y se incrementa para que sea único - test.text, test-1.txt, test-2.txt, etc.
memmons
Mi directorio de la Bandeja de entrada está vacío, pero tengo el botón "Abrir en" que no responde en Safari del que hablas. Hace años, mi aplicación funcionaba bien, pero de repente dejó de funcionar. Sospecho que Apple cambió algo en Safari.
Bram
18

ADVERTENCIA GRANDE: Asegúrese de CIENTO POR CIENTO que su extensión no esté vinculada a algún tipo de mimo.

Usamos la extensión '.icz' para nuestros archivos personalizados, básicamente, para siempre, y Safari nunca te dejaba abrirlos diciendo "Safari no puede abrir este archivo". no importa lo que hicimos o probamos con las cosas de UT anteriores.

Finalmente, me di cuenta de que hay algunas funciones UT * C que puedes usar para explorar varias cosas, y mientras .icz da la respuesta correcta (nuestra aplicación):

En la aplicación se cargó en la parte superior, solo haz esto ...

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
                                                                   (CFStringRef)@"icz", 
                                                                   NULL);
CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

y poner un salto después de esa línea y ver qué son UTI y ur - en nuestro caso, era nuestro identificador como queríamos, y la url del paquete (ur) apuntaba a la carpeta de nuestra aplicación.

Pero el tipo MIME que Dropbox nos devuelve para nuestro enlace, que puede verificar haciendo, por ejemplo,

$ curl -D headers THEURLGOESHERE > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27393  100 27393    0     0  24983      0  0:00:01  0:00:01 --:--:-- 28926
$ cat headers
HTTP/1.1 200 OK
accept-ranges: bytes
cache-control: max-age=0
content-disposition: attachment; filename="123.icz"
Content-Type: text/calendar
Date: Fri, 24 May 2013 17:41:28 GMT
etag: 872926d
pragma: public
Server: nginx
x-dropbox-request-id: 13bd327248d90fde
X-RequestId: bf9adc56934eff0bfb68a01d526eba1f
x-server-response-time: 379
Content-Length: 27393
Connection: keep-alive

El tipo de contenido es lo que queremos. Dropbox afirma que esta es una entrada de texto / calendario. Excelente. Pero en mi caso, YA Traté de poner texto / calendario en los tipos mime de mi aplicación, y todavía no funciona. En cambio, cuando trato de obtener la UTI y la URL del paquete para el texto / calendario mimetype,

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
                                                                   (CFStringRef)@"text/calendar", 
                                                                   NULL);

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Veo "com.apple.ical.ics" como la UTI y "... / MobileCoreTypes.bundle /" como la URL del paquete. No es nuestra aplicación, sino Apple. Así que trato de poner com.apple.ical.ics en LSItemContentTypes junto con el mío, y en UTConformsTo en la exportación, pero no voy.

Básicamente, si Apple cree que en algún momento quiere manejar algún tipo de tipo de archivo (eso podría crearse 10 años después de que su aplicación esté activa, tenga en cuenta), tendrá que cambiar la extensión porque simplemente no le permitirán manejar El tipo de archivo.

Kalle
fuente
¡Gracias por la útil advertencia!
RockSolid
0

Para manejar cualquier tipo de archivos para mi propia aplicación, uso esta configuración para CFBundleDocumentTypes:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>IPA</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.item</string>
                <string>public.content</string>
                <string>public.data</string>
                <string>public.database</string>
                <string>public.composite-content</string>
                <string>public.contact</string>
                <string>public.archive</string>
                <string>public.url-name</string>
                <string>public.text</string>
                <string>public.plain-text</string>
                <string>public.source-code</string>
                <string>public.executable</string>
                <string>public.script</string>
                <string>public.shell-script</string>
                <string>public.xml</string>
                <string>public.symlink</string>
                <string>org.gnu.gnu-zip-archve</string>
                <string>org.gnu.gnu-tar-archive</string>
                <string>public.image</string>
                <string>public.movie</string>
                <string>public.audiovisual-​content</string>
                <string>public.audio</string>
                <string>public.directory</string>
                <string>public.folder</string>
                <string>com.apple.bundle</string>
                <string>com.apple.package</string>
                <string>com.apple.plugin</string>
                <string>com.apple.application-​bundle</string>
                <string>com.pkware.zip-archive</string>
                <string>public.filename-extension</string>
                <string>public.mime-type</string>
                <string>com.apple.ostype</string>
                <string>com.apple.nspboard-typ</string>
                <string>com.adobe.pdf</string>
                <string>com.adobe.postscript</string>
                <string>com.adobe.encapsulated-​postscript</string>
                <string>com.adobe.photoshop-​image</string>
                <string>com.adobe.illustrator.ai-​image</string>
                <string>com.compuserve.gif</string>
                <string>com.microsoft.word.doc</string>
                <string>com.microsoft.excel.xls</string>
                <string>com.microsoft.powerpoint.​ppt</string>
                <string>com.microsoft.waveform-​audio</string>
                <string>com.microsoft.advanced-​systems-format</string>
                <string>com.microsoft.advanced-​stream-redirector</string>
                <string>com.microsoft.windows-​media-wmv</string>
                <string>com.microsoft.windows-​media-wmp</string>
                <string>com.microsoft.windows-​media-wma</string>
                <string>com.apple.keynote.key</string>
                <string>com.apple.keynote.kth</string>
                <string>com.truevision.tga-image</string>
            </array>
            <key>CFBundleTypeIconFiles</key>
            <array>
                <string>Icon-76@2x</string>
            </array>
        </dict>
    </array>
SLdragon
fuente