Extensiones de iOS en Xamarin.iOS

Creación de extensiones en vídeo de iOS

Las extensiones, como se introdujo en iOS 8, son UIViewControllers especializadas y son presentadas por iOS dentro de contextos estándar, como dentro del Centro de notificaciones, como tipos de teclado personalizados solicitados por el usuario para realizar entradas especializadas u otros contextos, como editar una foto donde la extensión puede proporcionar filtros de efectos especiales.

Todas las extensiones se instalan junto con una aplicación de contenedor (con ambos elementos escritos mediante las Unified API de 64 bits) y se activan desde un punto de extensión determinado en una aplicación host. Y dado que se utilizarán como complementos de las funciones del sistema existente, deben ser de alto rendimiento, ligeras y sólidas.

Puntos de extensión

Tipo Descripción Punto de extensión Aplicación host
Action Editor o visor especializado para un tipo de medio determinado com.apple.ui-services Any
Proveedor de documentos Permite que la aplicación use un almacén de documentos remoto com.apple.fileprovider-ui Aplicaciones que usan un UIDocumentPickerViewController
Teclado Teclados alternativos com.apple.keyboard-service Any
Edición de fotos Manipulación y edición de fotos com.apple.photo-editing Editor Photos.app
Compartir Comparte datos con redes sociales, servicios de mensajería, etc. com.apple.share-services Any
Hoy Los "widgets" que aparecen en la pantalla Hoy o en el Centro de notificaciones com.apple.widget-extensions Centro de notificaciones y Hoy

Se agregaron puntos de extensión adicionales en iOS 10 e iOS 12. Puede encontrar la tabla completa de todos los tipos admitidos en la Guía de programación de extensiones de aplicaciones de iOS.

Limitaciones

Las extensiones tienen varias limitaciones, algunas de las cuales son universales para todos los tipos (por ejemplo, ningún tipo de extensión puede acceder a las cámaras o micrófonos), mientras que otros tipos de extensión pueden tener limitaciones específicas en su uso (por ejemplo, los teclados personalizados no se pueden usar para campos de entrada de datos seguros como para contraseñas).

Las limitaciones universales son:

Para conocer las limitaciones individuales, consulte la Guía de programación de extensiones de aplicaciones de Apple.

Distribución, instalación y ejecución de extensiones

Las extensiones se distribuyen desde dentro de una aplicación de contenedor, que, a su vez, se envía y distribuye a través de la App Store. Las extensiones distribuidas con la aplicación se instalan en ese momento, pero el usuario debe habilitar cada extensión explícitamente. Los diferentes tipos de extensiones están habilitados de diferentes maneras; varios requieren que el usuario vaya a la aplicación Configuración y las habilite desde allí. Mientras tanto, otras se activan en el momento del uso, por ejemplo, la extensión Compartir al enviar una foto.

La aplicación en la que se usa la extensión (donde el usuario encuentra el punto de extensión) se conoce como la Aplicación host, ya que es la aplicación que hospeda la extensión cuando se ejecuta. La aplicación que instala la extensión es la aplicación de contenedor, ya que es la aplicación que contenía la extensión cuando se instaló.

Normalmente, la aplicación de contenedor describe la extensión y guía al usuario a través del proceso de habilitación.

Depuración y versiones de lanzamiento de extensiones

Los límites de memoria para las extensiones de aplicación en ejecución son significativamente inferiores a los límites de memoria aplicados a una aplicación en primer plano. Los simuladores que ejecutan iOS tienen menos restricciones aplicadas a las extensiones y puede ejecutar la extensión sin problemas. Sin embargo, ejecutar la misma extensión en un dispositivo puede provocar resultados inesperados, incluido el bloqueo de la extensión o la finalización agresiva del sistema. Por lo tanto, asegúrese de compilar y probar la extensión en un dispositivo antes de enviarlo.

Debe asegurarse de que se aplican las siguientes opciones de configuración al proyecto de contenedor y a todas las extensiones a las que se hace referencia:

  1. Cree un paquete de aplicación en la configuración de Versión.
  2. En la configuración del proyecto de Compilación de iOS, establezca la opción Comportamiento del vinculador en Vincular solo SDK del marco o Vincular todo.
  3. En la configuración del proyecto de Depuración de iOS, desactive las opciones Habilitar depuración y Habilitar generación de perfiles.

Ciclo de vida de la extensión

Una extensión puede ser tan simple como un único UIViewController o extensiones más complejas que presentan varias pantallas de interfaz de usuario. Cuando el usuario encuentra Puntos de extensión (por ejemplo, al compartir una imagen), tendrá la oportunidad de elegir entre las extensiones registradas para ese punto de extensión.

Si elige una de las extensiones de la aplicación, se creará una instancia de su UIViewController y comenzará el ciclo de vida normal del controlador de vistas. Sin embargo, a diferencia de las aplicaciones normales, que se suspenden pero no se cierran cuando el usuario termina de interactuar con ellas, las extensiones se cargan, se ejecutan y se cierran repetidamente.

Las extensiones pueden comunicarse con sus aplicaciones host a través de un objeto NSExtensionContext. Algunas extensiones tienen operaciones que reciben devoluciones de llamada asincrónicas con los resultados. Estas devoluciones de llamada se ejecutarán en subprocesos en segundo plano y la extensión debe tener esto en cuenta; por ejemplo, mediante NSObject.InvokeOnMainThread si quieren actualizar la interfaz de usuario. Consulte la sección Comunicación con la aplicación host siguiente para obtener más información.

De forma predeterminada, las extensiones y sus aplicaciones de contenedor no se pueden comunicar, a pesar de instalarse juntas. En algunos casos, la aplicación de contenedor es básicamente un contenedor de "envío" vacío cuyo propósito se sirve una vez instalada la extensión. Sin embargo, si las circunstancias lo exigen, la aplicación de contenedor y la extensión pueden compartir recursos desde un área común. Además, una extensión de Hoy puede solicitar su aplicación de contenedor para abrir una dirección URL. Este comportamiento se muestra en el Widget de cuenta regresiva de eventos.

Creación de una extensión

Las extensiones (y sus aplicaciones de contenedor) deben ser archivos binarios de 64 bits y compilarse con las Unified API de Xamarin.iOS. Al desarrollar una extensión, las soluciones contendrán al menos dos proyectos: la aplicación de contenedor y un proyecto para cada extensión que proporciona el contenedor.

Requisitos del proyecto de aplicación de contenedor

La aplicación de contenedor que se usa para instalar la extensión tiene los siguientes requisitos:

  • Debe mantener una referencia al proyecto de extensión.
  • Debe ser una aplicación completa (debe poder iniciarse y ejecutarse correctamente) incluso si no hace nada más que proporcionar una manera de instalar una extensión.
  • Debe tener un identificador de agrupación que sea la base para el identificador de agrupación del proyecto de extensión (consulte la sección siguiente para obtener más detalles).

Requisitos del proyecto de extensión

Además, el proyecto de la extensión tiene los siguientes requisitos:

  • Debe tener un identificador de agrupación que comience con el identificador de lote de la aplicación de contenedor. Por ejemplo, si la aplicación de contenedor tiene un identificador de agrupación de com.myCompany.ContainerApp, el identificador de la extensión podría ser com.myCompany.ContainerApp.MyExtension:

    Identificadores de agrupación

  • Debe definir la clave NSExtensionPointIdentifier, con un valor adecuado (por ejemplo com.apple.widget-extension, para un widget del Centro de notificaciones de Hoy), en su archivo Info.plist.

  • También debe definir o bien la clave NSExtensionMainStoryboard o la clave NSExtensionPrincipalClass en su archivo Info.plist con un valor adecuado:

    • Use la clave NSExtensionMainStoryboard para especificar el nombre del Guión gráfico que presenta la interfaz de usuario principal para la extensión (menos .storyboard). Por ejemplo, Main para el archivo Main.storyboard.
    • Use la clave NSExtensionPrincipalClass para especificar la clase que se inicializará cuando se inicie la extensión. El valor debe coincidir con el valor Register del UIViewController:

    Registro de clases principal

Es posible que determinados tipos de extensiones tengan requisitos adicionales. Por ejemplo, una clase principal de la extensión Hoy o Centro de notificaciones debe implementar INCWidgetProviding.

Importante

Si inicia el proyecto con una de las plantillas de extensiones proporcionadas por Visual Studio para Mac, la mayoría de estos requisitos (si no todos) se proporcionarán y cumplirán automáticamente con la plantilla.

Tutorial

En el siguiente tutorial, creará un widget de Hoy de ejemplo que calcula el día y el número de días restantes en el año:

Un widget de Hoy de ejemplo que calcula el día y el número de días restantes en el año

Creación de la solución

Para crear la solución necesaria, haga lo siguiente:

  1. En primer lugar, cree un proyecto de Aplicación de vista única de iOS y haga clic en el botón Siguiente:

    En primer lugar, cree un proyecto de Aplicación de vista única de iOS y haga clic en el botón Siguiente

  2. Llame al proyecto TodayContainer y haga clic en el botón Siguiente:

    Llame al proyecto TodayContainer y haga clic en el botón Siguiente

  3. Compruebe el Nombre del proyecto y SolutionName y haga clic en el botón Crear para crear la solución:

    Compruebe el Nombre del proyecto y SolutionName y haga clic en el botón Crear para crear la solución

  4. A continuación, en el Explorador de soluciones, haga clic con el botón derecho en la solución y agregue un nuevo Proyecto de extensión de iOS desde la plantilla Extensión de hoy:

    A continuación, en el Explorador de soluciones, haga clic con el botón derecho en la solución y agregue un nuevo Proyecto de extensión de iOS desde la plantilla Extensión de hoy

  5. Llame al proyecto DaysRemaining y haga clic en el botón Siguiente:

    Llame al proyecto DaysRemaining y haga clic en el botón Siguiente

  6. Revise el proyecto y haga clic en el botón Crear para crearlo:

    Revise el proyecto y haga clic en el botón Crear para crearlo

La solución resultante debe tener ahora dos proyectos, como se muestra aquí:

La solución resultante debe tener ahora dos proyectos, como se muestra aquí

Creación de la interfaz de usuario de la extensión

A continuación, deberá diseñar la interfaz del widget Hoy. Esto puede hacerse mediante un guión gráfico o creando la interfaz de usuario en el código. Ambos métodos se tratarán a continuación en detalle.

Uso de guiones gráficos

Para compilar la interfaz de usuario con un guión gráfico, haga lo siguiente:

  1. En el Explorador de soluciones, haga doble clic en el archivo Main.storyboard del proyecto de extensión para abrirlo y editarlo:

    Haga doble clic en el archivo Main.storyboard de proyectos de extensión para abrirlo para su edición

  2. Seleccione la etiqueta que se agregó automáticamente a la interfaz de usuario por plantilla y asígnele el nombre TodayMessage en la pestaña Widget del Explorador de propiedades:

    Seleccione la etiqueta que se agregó automáticamente a la interfaz de usuario por plantilla y asígnele el nombre TodayMessage en la pestaña Widget del Explorador de propiedades

  3. Guarde los cambios en el Storyboard.

Mediante código

Para compilar la interfaz de usuario en el código, haga lo siguiente:

  1. En el Explorador de soluciones, seleccione el proyecto DaysRemaining, agregue una nueva clase y llámela CodeBasedViewController:

    Seleccione el proyecto DaysRemaining, agregue una nueva clase y llámela CodeBasedViewController

  2. De nuevo, en el Explorador de soluciones, haga doble clic en el archivo Info.plist de la extensión para abrirlo y editarlo:

    Haga doble clic en el archivo Info.plist de extensiones para abrirlo para su edición

  3. Seleccione la Vista de origen (en la parte inferior de la pantalla) y abra el nodo NSExtension:

    Seleccione la vista de origen en la parte inferior de la pantalla y abra el nodo NSExtension

  4. Quite la clave NSExtensionMainStoryboard y agregue una NSExtensionPrincipalClass con el valor CodeBasedViewController:

    Quite la clave NSExtensionMainStoryboard y agregue un NSExtensionPrincipalClass con el valor CodeBasedViewController

  5. Guarde los cambios.

A continuación, edite el archivo CodeBasedViewController.cs y haga que tenga un aspecto similar al siguiente:

using System;
using Foundation;
using UIKit;
using NotificationCenter;
using CoreGraphics;

namespace DaysRemaining
{
  [Register("CodeBasedViewController")]
  public class CodeBasedViewController : UIViewController, INCWidgetProviding
  {
    public CodeBasedViewController ()
    {
    }

    public override void ViewDidLoad ()
    {
      base.ViewDidLoad ();

      // Add label to view
      var TodayMessage = new UILabel (new CGRect (0, 0, View.Frame.Width, View.Frame.Height)) {
        TextAlignment = UITextAlignment.Center
      };

      View.AddSubview (TodayMessage);

      // Insert code to power extension here...

    }
  }
}

Tenga en cuenta que el [Register("CodeBasedViewController")] coincide con el valor especificado para el NSExtensionPrincipalClass anterior.

Codificación de la extensión

Con la interfaz de usuario creada, abra el TodayViewController.cs o el archivo CodeBasedViewController.cs (basado en el método usado para crear la interfaz de usuario anterior), cambie el método ViewDidLoad y haga que tenga un aspecto similar al siguiente:

public override void ViewDidLoad ()
{
  base.ViewDidLoad ();

  // Calculate the values
  var dayOfYear = DateTime.Now.DayOfYear;
  var leapYearExtra = DateTime.IsLeapYear (DateTime.Now.Year) ? 1 : 0;
  var daysRemaining = 365 + leapYearExtra - dayOfYear;

  // Display the message
  if (daysRemaining == 1) {
    TodayMessage.Text = String.Format ("Today is day {0}. There is one day remaining in the year.", dayOfYear);
  } else {
    TodayMessage.Text = String.Format ("Today is day {0}. There are {1} days remaining in the year.", dayOfYear, daysRemaining);
  }
}

Si usa el método de interfaz de usuario basado en código, reemplace el comentario // Insert code to power extension here... por el nuevo código anterior. Después de llamar a la implementación base (e insertar una etiqueta para la versión basada en código), este código realiza un cálculo sencillo para obtener el día del año y cuántos días quedan. A continuación, muestra el mensaje en la etiqueta (TodayMessage) que creó en el diseño de la interfaz de usuario.

Tenga en cuenta que este proceso es similar al proceso normal de escritura de una aplicación. Las extensiones UIViewController tienen el mismo ciclo de vida que un controlador de vistas en una aplicación, excepto que las extensiones no tienen modos en segundo plano y no se suspenden cuando el usuario haya terminado de usarlos. En su lugar, las extensiones se inicializan repetidamente y se desasignan según sea necesario.

Creación de la interfaz de usuario de la aplicación de contenedor

Para este tutorial, la aplicación de contenedor simplemente se usa como método para enviar e instalar la extensión y no proporciona ninguna funcionalidad propia. Edite el archivo Main.storyboard de TodayContainer y agregue un texto que defina la función de la extensión y cómo instalarlo:

Edite el archivo Main.storyboard de TodayContainers y agregue un texto que defina la función de la extensión y cómo instalarlo

Guarde los cambios en el Storyboard.

Prueba de la extensión

Para probar la extensión en el simulador de iOS, ejecute la aplicación TodayContainer. Se mostrará la vista principal del contenedor:

Se mostrará la vista principal del contenedor

A continuación, presione el botón Inicio del simulador, desplácese hacia abajo desde la parte superior de la pantalla para abrir el Centro de notificaciones, seleccione la pestaña Hoy y haga clic en el botón Editar:

Presione el botón Inicio del simulador, desplácese hacia abajo desde la parte superior de la pantalla para abrir el Centro de notificaciones, seleccione la pestaña Hoy y haga clic en el botón Editar

Agregue la extensión DaysRemaining a la vista Hoy y haga clic en el botón Listo:

Agregue la extensión DaysRemaining a la vista Hoy y haga clic en el botón Listo

El nuevo widget se agregará a la vista Hoy y se mostrarán los resultados:

El nuevo widget se agregará a la vista Hoy y se mostrarán los resultados

Comunicación con la aplicación host

El ejemplo de extensión de Hoy que creó anteriormente no se comunica con su aplicación host (la pantalla Hoy). Si lo hiciera, usaría la propiedad ExtensionContext de las clases TodayViewController o CodeBasedViewController.

En el caso de las extensiones que recibirán datos de sus aplicaciones host, los datos están en forma de una matriz de objetos NSExtensionItem almacenada en la propiedad InputItemsde ExtensionContextde la extensión UIViewController.

Otras extensiones, como las extensiones de edición de fotos, pueden distinguir entre el usuario que completa o cancela el uso. Esto se indicará de vuelta a la aplicación host a través de los métodos CompleteRequest y CancelRequest de la propiedad ExtensionContext.

Para obtener más información, consulte Guía de programación de extensiones de aplicaciones de Apple.

Comunicación con la aplicación primaria

Un grupo de aplicaciones permite que aplicaciones diferentes (o una aplicación y sus extensiones) tengan acceso a una ubicación de almacenamiento de archivos compartidos. Los grupos de aplicaciones se pueden usar para datos como:

Para obtener más información, consulte la sección Grupos de aplicaciones de nuestra documentación sobre Cómo trabajar con funcionalidades.

MobileCoreServices

Al trabajar con extensiones, use un Identificador uniforme de tipo (UTI) para crear y manipular datos que se intercambian entre la aplicación, otras aplicaciones o servicios.

La clase estática MobileCoreServices.UTType define las siguientes propiedades auxiliares relacionadas con las definiciones de kUTType... de Apple:

  • kUTTypeAlembic - Alembic
  • kUTTypeAliasFile - AliasFile
  • kUTTypeAliasRecord - AliasRecord
  • kUTTypeAppleICNS - AppleICNS
  • kUTTypeAppleProtectedMPEG4Audio - AppleProtectedMPEG4Audio
  • kUTTypeAppleProtectedMPEG4Video - AppleProtectedMPEG4Video
  • kUTTypeAppleScript - AppleScript
  • kUTTypeApplication - Application
  • kUTTypeApplicationBundle - ApplicationBundle
  • kUTTypeApplicationFile - ApplicationFile
  • kUTTypeArchive - Archive
  • kUTTypeAssemblyLanguageSource - AssemblyLanguageSource
  • kUTTypeAudio - Audio
  • kUTTypeAudioInterchangeFileFormat - AudioInterchangeFileFormat
  • kUTTypeAudiovisualContent - AudiovisualContent
  • kUTTypeAVIMovie - AVIMovie
  • kUTTypeBinaryPropertyList - BinaryPropertyList
  • kUTTypeBMP - BMP
  • kUTTypeBookmark - Bookmark
  • kUTTypeBundle - Bundle
  • kUTTypeBzip2Archive - Bzip2Archive
  • kUTTypeCalendarEvent - CalendarEvent
  • kUTTypeCHeader - CHeader
  • kUTTypeCommaSeparatedText - CommaSeparatedText
  • kUTTypeCompositeContent - CompositeContent
  • kUTTypeConformsToKey - ConformsToKey
  • kUTTypeContact - Contact
  • kUTTypeContent - Content
  • kUTTypeCPlusPlusHeader - CPlusPlusHeader
  • kUTTypeCPlusPlusSource - CPlusPlusSource
  • kUTTypeCSource - CSource
  • kUTTypeData - Database
  • kUTTypeDelimitedText - DelimitedText
  • kUTTypeDescriptionKey - DescriptionKey
  • kUTTypeDirectory - Directory
  • kUTTypeDiskImage - DiskImage
  • kUTTypeElectronicPublication - ElectronicPublication
  • kUTTypeEmailMessage - EmailMessage
  • kUTTypeExecutable - Executable
  • kUTExportedTypeDeclarationsKey - ExportedTypeDeclarationsKey
  • kUTTypeFileURL - FileURL
  • kUTTypeFlatRTFD - FlatRTFD
  • kUTTypeFolder - Folder
  • kUTTypeFont - Font
  • kUTTypeFramework - Framework
  • kUTTypeGIF - GIF
  • kUTTypeGNUZipArchive - GNUZipArchive
  • kUTTypeHTML - HTML
  • kUTTypeICO - ICO
  • kUTTypeIconFileKey - IconFileKey
  • kUTTypeIdentifierKey - IdentifierKey
  • kUTTypeImage - Image
  • kUTImportedTypeDeclarationsKey - ImportedTypeDeclarationsKey
  • kUTTypeInkText - InkText
  • kUTTypeInternetLocation - InternetLocation
  • kUTTypeItem - Item
  • kUTTypeJavaArchive - JavaArchive
  • kUTTypeJavaClass - JavaClass
  • kUTTypeJavaScript - JavaScript
  • kUTTypeJavaSource - JavaSource
  • kUTTypeJPEG - JPEG
  • kUTTypeJPEG2000 - JPEG2000
  • kUTTypeJSON - JSON
  • kUTType3dObject - k3dObject
  • kUTTypeLivePhoto - LivePhoto
  • kUTTypeLog - Log
  • kUTTypeM3UPlaylist - M3UPlaylist
  • kUTTypeMessage - Message
  • kUTTypeMIDIAudio - MIDIAudio
  • kUTTypeMountPoint - MountPoint
  • kUTTypeMovie - Movie
  • kUTTypeMP3 - MP3
  • kUTTypeMPEG - MPEG
  • kUTTypeMPEG2TransportStream - MPEG2TransportStream
  • kUTTypeMPEG2Video - MPEG2Video
  • kUTTypeMPEG4 - MPEG4
  • kUTTypeMPEG4Audio - MPEG4Audio
  • kUTTypeObjectiveCPlusPlusSource - ObjectiveCPlusPlusSource
  • kUTTypeObjectiveCSource - ObjectiveCSource
  • kUTTypeOSAScript - OSAScript
  • kUTTypeOSAScriptBundle - OSAScriptBundle
  • kUTTypePackage - Package
  • kUTTypePDF - PDF
  • kUTTypePerlScript - PerlScript
  • kUTTypePHPScript - PHPScript
  • kUTTypePICT - PICT
  • kUTTypePKCS12 - PKCS12
  • kUTTypePlainText - PlainText
  • kUTTypePlaylist - Playlist
  • kUTTypePluginBundle - PluginBundle
  • kUTTypePNG - PNG
  • kUTTypePolygon - Polygon
  • kUTTypePresentation - Presentation
  • kUTTypePropertyList - PropertyList
  • kUTTypePythonScript - PythonScript
  • kUTTypeQuickLookGenerator - QuickLookGenerator
  • kUTTypeQuickTimeImage - QuickTimeImage
  • kUTTypeQuickTimeMovie - QuickTimeMovie
  • kUTTypeRawImage - RawImage
  • kUTTypeReferenceURLKey - ReferenceURLKey
  • kUTTypeResolvable - Resolvable
  • kUTTypeRTF - RTF
  • kUTTypeRTFD - RTFD
  • kUTTypeRubyScript - RubyScript
  • kUTTypeScalableVectorGraphics - ScalableVectorGraphics
  • kUTTypeScript - Script
  • kUTTypeShellScript - ShellScript
  • kUTTypeSourceCode - SourceCode
  • kUTTypeSpotlightImporter - SpotlightImporter
  • kUTTypeSpreadsheet - Spreadsheet
  • kUTTypeStereolithography - Stereolithography
  • kUTTypeSwiftSource - SwiftSource
  • kUTTypeSymLink - SymLink
  • kUTTypeSystemPreferencesPane - SystemPreferencesPane
  • kUTTypeTabSeparatedText - TabSeparatedText
  • kUTTagClassFilenameExtension - TagClassFilenameExtension
  • kUTTagClassMIMEType - TagClassMIMEType
  • kUTTypeTagSpecificationKey - TagSpecificationKey
  • kUTTypeText - Text
  • kUTType3DContent - ThreeDContent
  • kUTTypeTIFF - TIFF
  • kUTTypeToDoItem - ToDoItem
  • kUTTypeTXNTextAndMultimediaData - TXNTextAndMultimediaData
  • kUTTypeUniversalSceneDescription - UniversalSceneDescription
  • kUTTypeUnixExecutable - UnixExecutable
  • kUTTypeURL - URL
  • kUTTypeURLBookmarkData - URLBookmarkData
  • kUTTypeUTF16ExternalPlainText - UTF16ExternalPlainText
  • kUTTypeUTF16PlainText - UTF16PlainText
  • kUTTypeUTF8PlainText - UTF8PlainText
  • kUTTypeUTF8TabSeparatedText - UTF8TabSeparatedText
  • kUTTypeVCard - VCard
  • kUTTypeVersionKey - VersionKey
  • kUTTypeVideo - Video
  • kUTTypeVolume - Volume
  • kUTTypeWaveformAudio - WaveformAudio
  • kUTTypeWebArchive - WebArchive
  • kUTTypeWindowsExecutable - WindowsExecutable
  • kUTTypeX509Certificate - X509Certificate
  • kUTTypeXML - XML
  • kUTTypeXMLPropertyList - XMLPropertyList
  • kUTTypeXPCService - XPCService
  • kUTTypeZipArchive - ZipArchive

Observe el ejemplo siguiente:

using MobileCoreServices;
...

NSItemProvider itemProvider = new NSItemProvider ();
itemProvider.LoadItem(UTType.PropertyList ,null, (item, err) => {
    if (err == null) {
        NSDictionary results = (NSDictionary )item;
        NSString baseURI =
results.ObjectForKey("NSExtensionJavaScriptPreprocessingResultsKey");
    }
});

Para obtener más información, consulte la sección Grupos de aplicaciones de nuestra documentación sobre Cómo trabajar con funcionalidades.

Precauciones y consideraciones

Las extensiones tienen mucho menos memoria disponible que las aplicaciones. Se espera que se ejecuten rápidamente y con una intrusión mínima para el usuario y la aplicación en la que se hospedan. Sin embargo, una extensión también debe proporcionar una función distintiva y útil a la aplicación de consumo con una interfaz de usuario de marca que permita al usuario identificar la aplicación de contenedor o desarrollador de la extensión a la que pertenecen.

Dados estos requisitos estrictos, solo debe implementar extensiones que se han probado exhaustivamente y optimizado para el rendimiento y el consumo de memoria.

Resumen

Este documento ha tratado las extensiones, qué son, el tipo de puntos de extensión y las limitaciones conocidas impuestas en una extensión por iOS. Se ha descrito la creación, distribución, instalación y ejecución de extensiones y su ciclo de vida. Se proporcionó un tutorial sobre cómo crear un widget de Hoy sencillo que muestra dos maneras de crear la interfaz de usuario del widget mediante guiones gráficos o código. Se mostró cómo probar una extensión en el simulador de iOS. Por último, se explicó brevemente la comunicación con la aplicación host y algunas precauciones y consideraciones que se deben tomar al desarrollar una extensión.