Crear una extensión para compartir simple en la aplicación iOS 8

Las extensiones para compartir, introducidas en iOS 8, ofrecen a los usuarios una forma fácil y conveniente de compartir contenido con otras entidades, como sitios web para compartir en redes sociales o servicios de carga. Previamente, el intercambio de contenido normalmente suponía cambiar de una aplicación a otra, por ejemplo, mientras que la navegación en Safari, si usted quería compartir una dirección URL, copia, cambie a la aplicación que quería guardar o compartir en, realizar la acción y, a continuación, reanudar el surf en Safari. Con las extensiones para compartir, los usuarios ahora podrán compartir contenido con tu servicio directamente desde la aplicación que están utilizando, ya sea Safari, Fotos u otras aplicaciones. Esto no se limita a las aplicaciones del sistema. Cualquier aplicación personalizada que presente una instancia de la clase UIActivityViewController podrá ver su extensión compartida si la creó para que pueda manejar el tipo de archivo proporcionado por esa aplicación.

Vamos a crear una extensión para compartir que comparta fotos en una red social. Para simplificar las cosas, usaremos Imgur para esto, ya que permite a los usuarios cargar imágenes de forma anónima (sin que las imágenes estén vinculadas a una cuenta).

Al igual que cualquier otra extensión, una extensión compartida no puede ser una aplicación independiente; debe venir incluida con una aplicación contenedor. He creado un proyecto inicial que será nuestra aplicación contenedor. Descárguelo para seguirlo.

Cómo funciona la Aplicación de demostración

La aplicación es una aplicación simple llamada ImgurShare que el usuario puede usar para cargar imágenes en Imgur. Daré las instrucciones para que esté listo para ejecutarse en breve, pero primero déjame dar una visión general de la aplicación.

Su vista raíz es una vista de tabla que enumera los títulos que damos a las imágenes subidas a Imgur.

Para cargar una imagen, toque el botón + en la barra de navegación y se le presentará una vista que le permite seleccionar una imagen, ingresar un título para la imagen y cargarla en Imgur.

Después de cargar la imagen, cuando regrese a la vista de tabla, se mostrará el título de la imagen cargada. Cuando seleccione un elemento en la vista de tabla, se le mostrará la imagen cargada y su enlace en Imgur. Para mantenerlo simple, no incluí la funcionalidad de edición y eliminación.

Hay un botón Copiar URL en la barra de navegación de esta vista, que puede usar para copiar la URL de la imagen al portapapeles. Puedes probarlo copiando la URL, abriendo Safari y pegando el enlace. Verás tu imagen subida en Imgur.

Introducción

Con la vista general de la aplicación fuera del camino, ahora podemos configurarla. Hay un par de cosas que debes hacer para que funcione. En primer lugar, necesitará un ID de cliente de Imgur para usar su API y, en segundo lugar, deberá configurar un Grupo de aplicaciones. Necesita una cuenta de desarrollador para habilitar los grupos de aplicaciones. Para que una extensión comparta datos con su aplicación contenedor, debe configurar un Grupo de aplicaciones. Esto permitirá el acceso a un contenedor compartido entre la extensión y la aplicación contenedor.

Queremos que la extensión tenga acceso al contenedor compartido por dos razones: en primer lugar, al igual que la aplicación contenedor, todas las imágenes cargadas a través de la extensión se guardarán y estarán disponibles para su visualización a través de la aplicación contenedor y, en segundo lugar, usamos una sesión de fondo para la carga que requiere que la imagen se guarde primero antes de cargarla, por lo que guardamos una imagen temporal en el contenedor compartido que se utiliza en la tarea de carga en segundo plano. Usamos la carga en segundo plano porque los usuarios tienden a volver a la aplicación de host inmediatamente después de terminar su tarea en extensiones, por lo que si la carga es potencialmente larga, queremos que se complete incluso cuando se termine la extensión.

Para obtener el id de cliente de Imgur, inicie sesión en imgur.com o registre una cuenta en imgur.com/register.Una vez que haya iniciado sesión, haga clic en su nombre de usuario en la parte superior derecha de la pantalla y seleccione Configuración.

a Continuación, seleccione Aplicaciones en el menú de la derecha.

Selecciona Crear la tuya en Aplicaciones utilizadas.

Haga clic en Registrar una aplicación en el menú de la izquierda y seleccione Registrar su aplicación como se muestra.

En el formulario de solicitud, ingrese lo que desee para el nombre de la solicitud. Para Tipo de autorización, seleccione Autorización OAuth 2 sin una URL de devolución de llamada, ingrese su dirección de correo electrónico en Correo electrónico e ingrese lo que desee para la descripción. Ingrese el texto de seguridad en el cuadro y envíe el formulario.

Después de un envío exitoso, se le mostrará su ID de Cliente y secreto de cliente.

Copie el ID de cliente y abra UploadImageService.swift (encuéntralo en el grupo ImgurKit) y pégalo en la instrucción que se muestra.

1
private let imgurClientId = «IMGUR_CLIENT_ID»

Para configurar el Grupo de aplicaciones, primero cambie el identificador de paquete de la aplicación. Seleccione ImgurShare en el Navegador de proyectos y, a continuación, seleccione el destino ImgurShare de la lista de destinos. En la ficha General, cambie el identificador de paquete de com.appcoda.ImgurShare a otra cosa. Necesitas un identificador diferente porque el identificador que usas para tu grupo de aplicaciones debe coincidir con el identificador de paquete y debe ser único.

A continuación, vaya a la pestaña Capacidades y active el interruptor Grupos de aplicaciones. Añadir un nuevo grupo y el nombre del grupo.com..ImgurShare. En mi caso, he de grupo.com.appcoda.ImgurShare.

Crear el recurso Compartido de Extensión

Abrir AddImageViewController.archivo swift y en la función shareImage(imageTitle:, imageToUpload:), cambie el identificador del contenedor para que coincida con el grupo que creó.

1
config.sharedContainerIdentifier = «grupo.com.appcoda.ImgurShare»

Abierto ImageService.swift y haga lo mismo con la siguiente instrucción en la función tempContainerURL(image:, name:).

Haga lo mismo con la instrucción mostrada en la función getFileUrl() de la misma clase.

ahora puede ejecutar y probar la aplicación.

A continuación crearemos la extensión para compartir. Seleccione el proyecto ImgurShare en el Navegador de proyectos y, a continuación, vaya a Editor > Agregar destino > iOS > Extensión de aplicación > Extensión compartida

En la siguiente pantalla, establezca el nombre del producto en ImgurUpload y deje los campos restantes en su valor predeterminado. Haga clic en Finalizar y active el esquema ImgurUpload

A continuación, configure el Grupo de aplicaciones para el destino ImgurUpload. Seleccione el proyecto ImgurShare en el Navegador de proyectos y, a continuación, seleccione el destino ImgurUpload. En la pestaña Capacidades, active el interruptor Grupos de aplicaciones y seleccione el grupo que creó anteriormente para el destino ImgurShare.

Para habilitar el uso compartido de código entre la extensión y la aplicación contenedor, coloco el código en un marco. Tenemos que vincular esto con el objetivo de ImgurUpload.

Con el destino ImgurUpload seleccionado, en la pestaña General, haga clic en el botón + en la sección Frameworks y Bibliotecas vinculados. Selecciona ImgurKit.de la lista y haga clic en Agregar.

Con esa configuración, veamos ahora los archivos generados cuando creamos la extensión. Expanda el grupo ImgurUpload y verá un archivo de guion gráfico, un archivo de derechos, un controlador de vista y un archivo plist en el grupo Archivos de soporte. El archivo de derechos de una extensión, al igual que en la aplicación contenedor, se genera al configurar grupos de aplicaciones. Contiene detalles de tu grupo de aplicaciones. Al igual que en las Extensiones de acción, puedes usar un archivo JavaScript para obtener contenido de páginas web en Safari. No usaremos esto en nuestra extensión, pero para obtener una idea sobre cómo utilizar archivos JavaScript para obtener datos de la aplicación host al controlador de vista de la extensión, puede consultar el artículo anterior que hicimos sobre las extensiones de acción. El proceso y la configuración son bastante similares.

Puede usar el archivo de guion gráfico para crear una interfaz personalizada (o hacerlo en código), pero las extensiones para compartir vienen con una vista de composición predeterminada que usaremos. Su interfaz es similar a la vista de redacción que se obtiene cuando se comparte algo en Twitter o Facebook.

Necesitamos especificar el tipo de contenido que admite nuestra extensión estableciendo su regla de activación en el archivo plist. Abrir Información.plist y expanda la tecla NSExtension. A continuación, expanda la tecla NSExtensionAttributes para llegar a la regla Nsextensionactivation. De forma predeterminada, se establece en TRUEPREDICATE, lo que significa que la extensión siempre estará disponible cuando el usuario quiera compartir contenido. Debes cambiar esto y hacerlo específico si quieres que la app sea aprobada por la App Store. Cambie su tipo a Diccionario y agregue un nuevo par clave-valor. Establezca el nombre de la clave en Nsextensionactivationsupportsimagewithaxcount, escriba en Número y valor en 1. Esto especifica que la extensión admite compartir una sola imagen a la vez.

Mirando la clase ShareViewController, encontrará los siguientes stubs de método.

  • isContentValid () – Aquí es donde se valida la entrada del usuario. Valida la entrada de texto, así como el contenido que se va a compartir y devuelve true si la validación pasa. El botón Publicar en la vista de redacción permanecerá desactivado hasta que se devuelva true.
  • didSelectPost (): Se llama después de que el usuario toque el botón Publicar y es aquí donde carga el contenido que se comparte. Una vez programada la carga, debe llamar a completeRequestReturningItems(, completeHandler:) para que la aplicación host pueda desbloquear su interfaz de usuario. Cuando la solicitud de carga se realiza, llama al controlador de finalización que se pasó a la llamada de función mencionada anteriormente.
  • configurationItems (): La vista de composición predeterminada de la extensión compartida le permite establecer lo que aparece en la parte inferior de la vista mediante celdas de vista de tabla. Para ello, debe devolver una matriz de objetos SLComposeSheetConfigurationItem si tiene configuraciones para que el usuario las establezca. De lo contrario, devuelve una matriz vacía.

Agregue las siguientes importaciones a la clase ShareViewController.

1
2

importación ImgurKit
importar MobileCoreServices

Agregue la siguiente variable a la clase. Esto mantendrá la imagen seleccionada por el usuario.

1
var selectedImage: UIImage?

A continuación, sobrescribiremos viewDidLoad() para extraer la imagen de los elementos adjuntos en extensionContext. Cuando el usuario publica una imagen, se incluye con otros metadatos y se pasa a la extensión a través del objeto extensionContext. Agregue lo siguiente a la clase.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

reemplazar func viewDidLoad () {
super.viewDidLoad()
let content = extensionContext!.inputItems as NSExtensionItem
let contentType = kUTTypeImage as String
for attachment in content.attachments as {
if attachment.hasItemConformingToTypeIdentifier(contentType) {
attachment.loadItemForTypeIdentifier(contentType, options: nil) { data, error in
if error == nil {
let url = data as NSURL
if let imageData = NSData(contentsOfURL: url) {
self.selectedImage = UIImage (datos: ImageData)
}
} else {
let alert = UIAlertController (título: «Error», mensaje: «Error al cargar la imagen», Estilo preferido: .Alerta)
let action = UIAlertAction (título: «Error», estilo: .Cancelar) {_en
uno mismo.Dismissviewcontroleranimated (verdadero, finalización: nil)
}
alerta.addAction (acción)
self.presentViewController (alerta, animación: verdadero, finalización: nil)
}
}
}
}
}

Aquí extraemos el archivo adjunto en el elemento de la NSItemProvider objeto, a continuación, comprobar para ver si el archivo adjunto se ajusta al tipo de kUTTypeImage. kUTTypeImage es una constante de cadena definida por el sistema para identificadores de tipos uniformes de núcleo definidos en el marco de MobileCoreServices. Lo usamos para identificar tipos de archivos adjuntos.

La imagen está envuelta en la clase NSItemProvider, por lo que primero necesitamos cargarla usando loadItemForTypeIdentifier(). Si esto tiene éxito, cargamos la imagen desde la url donde está almacenada (cuando se extrae de NSItemProvider, las imágenes se guardan en el disco). A continuación, establecemos la variable selectedImage con la imagen. En caso de error, se mostrará una alerta al usuario.

A continuación, modifique la función isContentValid () como se muestra.

1
2
3
4
5
6
7
8
9

reemplazar func isContentValid() -> Bool {
si vamos a img = selectedImage{
si!!!Contenido.isEmpty {
devuelve true
}
}
devolver falso
}

Esta comprobación para asegurarse de que una imagen está seleccionada y el usuario escribe en alguna entrada antes de poder publicar.

Modifique didSelectPost () de la siguiente manera.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

reemplazar func didSelectPost() {
vamos a defaultSession = UploadImageService.Servicio compartido.session
let defaultSessionConfig = defaultSession.configuración
let defaultHeaders = defaultSessionConfig.Encabezados Httpadditional
let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithidentifier(«com.appcoda.ImgurShare.bkgrdsession»)
config.sharedContainerIdentifier = «group.com.appcoda.ImgurShare»
config.HTTPAdditionalHeaders = defaultHeaders
let session = NSURLSession(configuration: config, delegate: UploadImageService.sharedService, delegateQueue: NSOperationQueue.mainQueue())
let completion: (TempImage?, NSError?, NSURL?) -> () = { image, error, tempURL in
if error == nil {
if let imageURL = image?.link {
let image = Image(imgTitle: self.contentText, imgImage: self.¡Imagen seleccionada!)
imagen.url = imageUrl
let imageService = ImageService.sharedService
imageService.addImage (imagen)
imageService.Guardarimágenes()
}
if let container = tempURL {
var delError: NSError?
si NSFileManager.defaultManager ().isDeletableFileAtPath(contenedor.¡camino!) {
let success = NSFileManager.defaultManager ().removeItemAtPath(contenedor.¡camino!, error: &delError)
if(!éxito) {
println («Error al eliminar el archivo en la ruta: \(error?.description)»)
}
}
}
} else {
println(«Error uploading image: \(error!)»)
if let container = tempURL {
var delError: NSError?
if NSFileManager.defaultManager().isDeletableFileAtPath(container.path!) {
let success = NSFileManager.defaultManager().removeItemAtPath(container.path!, error: &delError)
if(!success) {
println(«Error removing file at path: \(error?.descripción)»)
}
}
}
}
}
vamos a title = contentText
UploadImageService.Servicio compartido.uploadImage (Imagen seleccionada!, título: título, sesión: sesión, finalización: finalización)
yo.¿Contenido de extensión?.completeRequestReturningItems(, nil)
}

Reemplazar la Aplicación identificador de Grupo en la declaración de abajo con su propio.

1
config.sharedContainerIdentifier = «grupo.com.appcoda.ImgurShare»

Aquí se define el fondo de sesión vamos a utilizar para la carga. Luego definimos el bloque de finalización al que se llamará cuando se complete la solicitud. En el bloque de finalización, comprobamos si la carga se realizó correctamente y, de ser así, guardamos la imagen (las imágenes guardadas aquí se cargarán en la vista de tabla de la aplicación contenedor). A continuación, eliminamos la imagen temporal que se había guardado en el disco durante la solicitud en segundo plano. Si la carga falla, también eliminamos la imagen temporal y no la guardamos para verla más tarde en la aplicación contenedor. Solo queremos que la aplicación contenedor muestre imágenes que se cargaron correctamente en Imgur.

Tenga en cuenta el uso de contentText. Esta propiedad contiene la entrada de texto del usuario.

Luego llamamos a la función uploadImage () en el framework ImgurKit para hacer la carga. Este método es asíncrono y volverá inmediatamente. Cuando la carga se complete o falle, se llamará al bloque de finalización.

A continuación, modifique configurationItems () como se muestra. Devolvemos una matriz vacía, ya que no agregaremos nada a la vista de composición de la extensión.

1
2
3

reemplazar func configurationItems() -> ! {
volver
}

Pruebas de la participación de Extensión

ahora Se puede ejecutar la aplicación. Asegúrese de que el esquema ImgurUpload esté seleccionado. Cuando se le solicite que elija una aplicación para ejecutar, elija Fotos. Una vez ejecutada, selecciona una foto y pulsa el botón Compartir. En la primera ejecución, deberá agregar su extensión a la hoja de uso compartido. Seleccione el botón Más a la derecha de los otros iconos para compartir y encienda el interruptor de la extensión, luego seleccione Listo.

De vuelta en la hoja para compartir, podrá ver el icono de su extensión junto a los otros iconos para compartir. Selecciona tu extensión, introduce texto y pulsa en Publicar.

La imagen se cargará en Imgur y se guardará en la aplicación contenedor. Para confirmar esto, vaya a la pantalla de inicio y abra ImgurShare. Verá el título que introdujo para la imagen y la imagen en sí en la vista de detalles.

Si abandona la aplicación contenedor y vuelve a la aplicación Fotos para compartir otra imagen, y vuelve a la aplicación contenedor, notará que la tabla no se actualiza automáticamente con el elemento agregado. Si selecciona una fila de tabla y, a continuación, vuelve a la vista de tabla, la tabla se actualizará. Necesitamos recargar los datos de la tabla cuando la aplicación vuelva a aparecer en primer plano. Para hacer esto primero agregue la siguiente función a la clase ImagesTableViewController.

1
2
3

func refreshTable() {
formato tableview.reloadData()
}

Luego en AppDelegate.swift, agregue lo siguiente a la función applicationWillEnterForeground ().

1
2

vamos a vc = ImagesTableViewController()
vc.actualiZable()

Ahora, cada vez que cargue una imagen a través de la extensión y devuelva la aplicación contenedor al primer plano, la tabla se actualizará.

Resumen

Que concluye este tutorial de Extensión para compartir. Espero que la guía sea útil para cualquiera que quiera crear una extensión para compartir. Puede descargar los archivos del proyecto aquí.

Nota: Al compartir un archivo a través de la extensión, notará un mensaje de error en el depurador «Error al heredar los permisos de CoreMedia de xxxx». Este parece ser un error común, y lo he encontrado al trabajar con las extensiones Today, Share y action. La extensión sigue funcionando bien a pesar del error. Buscando, parece ser común y en este post de Stackoverflow, alguien dice que su extensión funciona bien y fue aprobada por Apple a pesar de recibir el error. Por lo tanto, podría ser un error de Xcode. No estoy seguro. Puedes dejar tus pensamientos en el comentario.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.