Notificaciones avanzadas de usuario en Xamarin.iOS

Novedades de iOS 10, el marco de notificaciones de usuario permite la entrega y el control de notificaciones locales y remotas. Con este marco, una aplicación o la extensión de aplicación pueden programar la entrega de notificaciones locales especificando un conjunto de condiciones, como la ubicación o la hora del día.

Acerca de las notificaciones de usuario

El nuevo marco de notificaciones de usuario permite la entrega y el control de notificaciones locales y remotas. Con este marco, la aplicación o la extensión de aplicación pueden programar la entrega de notificaciones locales especificando un conjunto de condiciones, como la ubicación o la hora del día.

Además, la aplicación o la extensión pueden recibir (y potencialmente modificar) notificaciones locales y remotas a medida que se entregan al dispositivo iOS del usuario.

El nuevo marco de interfaz de usuario de notificación de usuario permite a una aplicación o extensión de aplicación personalizar la apariencia de las notificaciones locales y remotas cuando se presentan al usuario.

Este marco proporciona las siguientes maneras de que una aplicación pueda entregar notificaciones a un usuario:

  • Alertas visuales: donde la notificación se implementa desde la parte superior de la pantalla como un banner.
  • Sonido y vibraciones: se puede asociar a una notificación.
  • Distintivos en iconos de aplicación: donde el icono de la aplicación muestra un distintivo que muestra que el nuevo contenido está disponible. Por ejemplo, el número de mensajes de correo electrónico no leídos.

Además, en función del contexto actual del usuario, hay diferentes formas de presentar una notificación:

  • Si el dispositivo está desbloqueado, la notificación saldrá desde la parte superior de la pantalla como un banner.
  • Si el dispositivo está bloqueado, la notificación se mostrará en la pantalla de bloqueo del usuario.
  • Si el usuario no ha visto una notificación, puede abrir el Centro de notificaciones y ver las notificaciones disponibles en espera.

Una aplicación de Xamarin.iOS tiene dos tipos de notificaciones de usuario que puede enviar:

  • Notificaciones locales: estas se envían mediante aplicaciones instaladas localmente en el dispositivo de los usuarios.
  • Notificaciones remotas: se envían desde un servidor remoto y se presentan al usuario o desencadenan una actualización en segundo plano del contenido de la aplicación.

Para obtener más información, consulte nuestra documentación sobre notificaciones de usuario mejoradas.

La nueva interfaz de notificación de usuario

Las notificaciones de usuario en iOS 10 se presentan con un nuevo diseño de interfaz de usuario que proporciona más contenido, como título, subtítulo y datos adjuntos multimedia opcionales que se pueden presentar en la pantalla de bloqueo, como un banner en la parte superior del dispositivo o en el Centro de notificaciones.

Independientemente de dónde se muestre una notificación de usuario en iOS 10, presenta la misma apariencia y con las mismas características y funcionalidades.

En iOS 8, Apple introdujo Notificaciones accionables en las que el desarrollador podría adjuntar acciones personalizadas a una notificación y permitir al usuario realizar acciones en una notificación sin tener que iniciar la aplicación. En iOS 9, Apple ha mejorado las notificaciones accionables con respuesta rápida que permite al usuario responder a una notificación con entrada de texto.

Dado que las notificaciones de usuario son una parte más integral de la experiencia del usuario en iOS 10, Apple ha ampliado aún más las notificaciones accionables para admitir 3D Touch, donde el usuario presiona una notificación y se muestra una interfaz de usuario personalizada para proporcionar una interacción enriquecida con la notificación.

Cuando se muestra la interfaz de usuario de notificación de usuario personalizada, si el usuario interactúa con cualquier acción adjunta a la notificación, la interfaz de usuario personalizada se puede actualizar instantáneamente para proporcionar comentarios sobre lo que se ha cambiado.

Novedades de iOS 10, la API de interfaz de usuario de notificación de usuario permite que una aplicación de Xamarin.iOS aproveche fácilmente estas nuevas características de interfaz de usuario de notificación de usuario.

Adición de datos adjuntos multimedia

Uno de los elementos más comunes que se comparten entre los usuarios es fotos, por lo que iOS 10 agregó la capacidad de adjuntar un elemento multimedia (como una foto) directamente a una notificación, donde se presentará y estará disponible fácilmente para el usuario junto con el resto del contenido de la notificación.

Sin embargo, debido a los tamaños implicados en el envío de incluso una imagen pequeña, adjuntarlo a una carga de notificación remota resulta poco práctico. Para controlar esta situación, el desarrollador puede usar la nueva extensión de servicio en iOS 10 para descargar la imagen de otro origen (como un almacén de datos de CloudKit) y adjuntarla al contenido de la notificación antes de que se muestre al usuario.

Para que una extensión de servicio modifique una notificación remota, su carga debe marcarse como mutable. Por ejemplo:

{
    aps : {
        alert : "New Photo Available",
        mutable-content: 1
    },
    my-attachment : "https://example.com/photo.jpg"
}

Eche un vistazo a la información general siguiente del proceso:

Adding Media Attachments process

Una vez que la notificación remota se entrega al dispositivo (a través de APN), la extensión de servicio puede descargar la imagen necesaria a través de cualquier medio deseado (por ejemplo, un NSURLSession) y después de recibir la imagen, puede modificar el contenido de la notificación y mostrarla al usuario.

A continuación se muestra un ejemplo de cómo se puede controlar este proceso en el código:

using System;
using Foundation;
using UIKit;
using UserNotifications;

namespace MonkeyNotification
{
    public class NotificationService : UNNotificationServiceExtension
    {
        #region Constructors
        public NotificationService (IntPtr handle) : base(handle)
        {
        }
        #endregion

        #region Override Methods
        public override void DidReceiveNotificationRequest (UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
        {
            // Get file URL
            var attachementPath = request.Content.UserInfo.ObjectForKey (new NSString ("my-attachment"));
            var url = new NSUrl (attachementPath.ToString ());

            // Download the file
            var localURL = new NSUrl ("PathToLocalCopy");

            // Create attachment
            var attachmentID = "image";
            var options = new UNNotificationAttachmentOptions ();
            NSError err;
            var attachment = UNNotificationAttachment.FromIdentifier (attachmentID, localURL, options , out err);

            // Modify contents
            var content = request.Content.MutableCopy() as UNMutableNotificationContent;
            content.Attachments = new UNNotificationAttachment [] { attachment };

            // Display notification
            contentHandler (content);
        }

        public override void TimeWillExpire ()
        {
            // Handle service timing out
        }
        #endregion
    }
}

Cuando se recibe la notificación de APN, la dirección personalizada de la imagen se lee del contenido y el archivo se descarga desde el servidor. A continuación, se crea un UNNotificationAttachement con un identificador único y la ubicación local de la imagen (como un NSUrl). Se crea una copia mutable del contenido de notificación y se agregan datos adjuntos multimedia. Por último, la notificación se muestra al usuario llamando a contentHandler.

Una vez que se ha agregado un archivo adjunto a una notificación, el sistema se encarga del movimiento y la administración del archivo.

Además de las notificaciones remotas presentadas anteriormente, los datos adjuntos multimedia también se admiten en las notificaciones locales, donde se crea el UNNotificationAttachement y se adjunta a la notificación junto con su contenido.

La notificación en iOS 10 admite datos adjuntos multimedia de imágenes (estáticas y GIF), audio o vídeo y el sistema mostrará automáticamente la interfaz de usuario personalizada correcta para cada uno de estos tipos de datos adjuntos cuando se presente la notificación al usuario.

Nota:

Se debe tener cuidado para optimizar el tamaño de los medios y el tiempo necesario para descargar los medios desde el servidor remoto (o para ensamblar los medios para notificaciones locales), ya que el sistema impone límites estrictos a ambos al ejecutar la extensión de servicio de la aplicación. Por ejemplo, considere la posibilidad de enviar una versión reducida de la imagen o un pequeño clip de un vídeo que se va a presentar en la notificación.

Creación de interfaces de usuario personalizadas

Para crear una interfaz de usuario personalizada para sus notificaciones de usuario, el desarrollador debe agregar una extensión de contenido de notificación (nueva a iOS 10) a la solución de la aplicación.

La extensión de contenido de notificación permite al desarrollador agregar sus propias vistas a la interfaz de usuario de notificación y extraer cualquier contenido que desee. A partir de iOS 12, las extensiones de contenido de notificación admiten controles de interfaz de usuario interactivos, como botones y controles deslizantes. Para obtener más información, consulte la documentación de notificaciones interactivas en iOS 12.

Para admitir la interacción del usuario con una notificación de usuario, se deben crear acciones personalizadas, registrarse con el sistema y adjuntarlas a la notificación antes de que se programe con el sistema. Se llamará a la extensión de contenido de notificación para controlar el procesamiento de estas acciones. Consulte la sección Trabajar con acciones de notificación del documento Notificaciones de usuario mejoradas para obtener más información sobre acciones personalizadas.

Cuando se presenta una notificación de usuario con una interfaz de usuario personalizada al usuario, tendrá los siguientes elementos:

A User Notification with a Custom UI elements

Si el usuario interactúa con las acciones personalizadas (presentadas debajo de la notificación), la interfaz de usuario se puede actualizar para proporcionar comentarios al usuario como lo que sucedió cuando invocó una acción determinada.

Adición de una extensión de contenido de notificación

Para implementar una interfaz de usuario de notificación de usuario personalizada en una aplicación de Xamarin.iOS, haga lo siguiente:

  1. Abra la solución de la aplicación en Visual Studio para Mac.

  2. Haga clic con el botón derecho en el nombre de la solución en el panel de solución y seleccione Agregar>Agregar nuevo proyecto.

  3. Seleccione iOS>Extensiones>Extensiones de contenido de notificaciones y haga clic en el botón Siguiente:

    Select Notification Content Extensions

  4. Escriba un nombre para la extensión y haga clic en el botón Siguiente:

    Enter a Name for the extension

  5. Ajuste el Nombre de proyecto o Nombre de la solución si es necesario y haga clic en el botón Crear:

    Adjust the Project Name and/or Solution Name

Cuando se agrega la extensión de contenido de notificación a la solución, se crearán tres archivos en el proyecto de la extensión:

  1. NotificationViewController.cs: este es el controlador de vista principal de la extensión de contenido de notificación.
  2. MainInterface.storyboard: donde el desarrollador establece la interfaz de usuario visible para la extensión de contenido de notificación en iOS Designer.
  3. Info.plist: controla la configuración de la extensión de contenido de notificación.

El archivo predeterminado NotificationViewController.cs es similar al siguiente:

using System;
using Foundation;
using UIKit;
using UserNotifications;
using UserNotificationsUI;

namespace MonkeyChatNotifyExtension
{
    public partial class NotificationViewController : UIViewController, IUNNotificationContentExtension
    {
        #region Constructors
        protected NotificationViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }
        #endregion

        #region Public Methods
        [Export ("didReceiveNotification:")]
        public void DidReceiveNotification (UNNotification notification)
        {
            label.Text = notification.Request.Content.Body;

            // Grab content
            var content = notification.Request.Content;

        }
        #endregion
    }
}

Se llama al método DidReceiveNotification cuando el usuario expande la notificación para que la extensión de contenido de notificación pueda rellenar la interfaz de usuario personalizada con el contenido del UNNotification. Para el ejemplo anterior, se ha agregado una etiqueta a la vista, expuesta al código con el nombre label y se usa para mostrar el cuerpo de la notificación.

Establecer las categorías de la extensión de contenido de notificación

El sistema debe informarse sobre cómo encontrar la extensión de contenido de notificación de la aplicación en función de las categorías específicas a las que responde. Haga lo siguiente:

  1. Haga doble clic en el archivo Info.plist de la extensión del panel de solución para abrirlo para editarlo.

  2. Cambie a la vista Código fuente.

  3. Expanda la clave NSExtension.

  4. Agregue la clave UNNotificationExtensionCategory como tipo String con el valor de la categoría a la que pertenece la extensión (en este ejemplo "event-invite):

    Add the UNNotificationExtensionCategory key

  5. Guarde los cambios.

Las categorías de extensión de contenido de notificación (UNNotificationExtensionCategory) usan los mismos valores de categoría que se usan para registrar acciones de notificación. En la situación en la que la aplicación usará la misma interfaz de usuario para varias categorías, cambie el UNNotificationExtensionCategory al tipo Array y proporcione todas las categorías necesarias. Por ejemplo:

Ocultar el contenido de notificación predeterminado

En la situación en la que la interfaz de usuario de notificación personalizada mostrará el mismo contenido que la notificación predeterminada (título, subtítulo y cuerpo que se muestra automáticamente en la parte inferior de la interfaz de usuario de notificación), esta información predeterminada se puede ocultar agregando la clave UNNotificationExtensionDefaultContentHidden a la clave NSExtensionAttributes como tipo booleano con un valor de YES en el archivoInfo.plist de la extensión:

Diseño de la interfaz de usuario personalizada

Para diseñar la interfaz de usuario personalizada de la extensión de contenido de notificación, haga doble clic en el archivo MainInterface.storyboard para abrirlo para editarlo en el Diseñador de iOS, arrastre en los elementos que necesita para compilar la interfaz deseada (por ejemplo, UILabels y UIImageViews).

Nota:

A partir de iOS 12, una extensión de contenido de notificación puede incluir controles interactivos, como botones y campos de texto. Para obtener más información, consulte la documentación de notificaciones interactivas en iOS 12.

Una vez que la interfaz de usuario se ha diseñado y los controles necesarios expuestos al código de C#, abra el NotificationViewController.cs para editar y modificar el método DidReceiveNotification para rellenar la interfaz de usuario cuando el usuario expanda la notificación. Por ejemplo:

using System;
using Foundation;
using UIKit;
using UserNotifications;
using UserNotificationsUI;

namespace MonkeyChatNotifyExtension
{
    public partial class NotificationViewController : UIViewController, IUNNotificationContentExtension
    {
        #region Constructors
        protected NotificationViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }
        #endregion

        #region Public Methods
        [Export ("didReceiveNotification:")]
        public void DidReceiveNotification (UNNotification notification)
        {
            label.Text = notification.Request.Content.Body;

            // Grab content
            var content = notification.Request.Content;

            // Display content in the UILabels
            EventTitle.Text = content.Title;
            EventDate.Text = content.Subtitle;
            EventMessage.Text = content.Body;

            // Get location and display
            var location = content.UserInfo ["location"].ToString ();
            if (location != null) {
                Event.Location.Text = location;
            }

        }
        #endregion
    }
}

Establecimiento del tamaño del área de contenido

Para ajustar el tamaño del área de contenido que se muestra al usuario, el código siguiente establece la propiedad PreferredContentSize en el método ViewDidLoad en el tamaño deseado. Este tamaño también se puede ajustar aplicando restricciones a la vista en el Diseñador de iOS, se deja que el desarrollador elija el método que funciona mejor para ellos.

Dado que el sistema de notificaciones ya se está ejecutando antes de invocar la extensión de contenido de notificación, el área de contenido comenzará a tamaño completo y se animará hasta el tamaño solicitado cuando se le presente al usuario.

Para eliminar este efecto, edite el archivo Info.plist para la extensión y establezca la clave UNNotificationExtensionInitialContentSizeRatio de la clave NSExtensionAttributes para escribir Número con un valor que represente la proporción deseada. Por ejemplo:

Uso de datos adjuntos multimedia en la interfaz de usuario personalizada

Dado que los datos adjuntos multimedia (como se ve en la sección anterior Adición de datos adjuntos multimedia) forman parte de la carga de notificación, se puede acceder a ellos y mostrarlos en la extensión de contenido de notificación como lo harían en la interfaz de usuario de notificación predeterminada.

Por ejemplo, si la interfaz de usuario personalizada anterior incluía un UIImageView que se expone al código de C#, se podría usar el código siguiente para rellenarlo con los datos adjuntos multimedia:

using System;
using Foundation;
using UIKit;
using UserNotifications;
using UserNotificationsUI;

namespace MonkeyChatNotifyExtension
{
    public partial class NotificationViewController : UIViewController, IUNNotificationContentExtension
    {
        #region Constructors
        protected NotificationViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }
        #endregion

        #region Public Methods
        [Export ("didReceiveNotification:")]
        public void DidReceiveNotification (UNNotification notification)
        {
            label.Text = notification.Request.Content.Body;

            // Grab content
            var content = notification.Request.Content;

            // Display content in the UILabels
            EventTitle.Text = content.Title;
            EventDate.Text = content.Subtitle;
            EventMessage.Text = content.Body;

            // Get location and display
            var location = content.UserInfo ["location"].ToString ();
            if (location != null) {
                Event.Location.Text = location;
            }

            // Get Media Attachment
            if (content.Attachements.Length > 1) {
                var attachment = content.Attachments [0];
                if (attachment.Url.StartAccessingSecurityScopedResource ()) {
                    EventImage.Image = UIImage.FromFile (attachment.Url.Path);
                    attachment.Url.StopAccessingSecurityScopedResource ();
                }
            }
        }
        #endregion
    }
}

Dado que el sistema administra los datos adjuntos multimedia, está fuera del espacio aislado de la aplicación. La extensión debe informar al sistema de que desea acceder al archivo llamando al método StartAccessingSecurityScopedResource. Cuando la extensión se realiza con el archivo, debe llamar al StopAccessingSecurityScopedResource para liberar su conexión.

Adición de acciones personalizadas a una interfaz de usuario personalizada

Los botones de acción personalizados se pueden usar para agregar interactividad a una interfaz de usuario de notificación personalizada. Consulte la sección Trabajar con acciones de notificación del documento Notificaciones de usuario mejoradas para obtener más información sobre las acciones personalizadas.

Además de las acciones personalizadas, la extensión de contenido de notificación también puede responder a las siguientes acciones integradas:

  • Acción predeterminada: es cuando el usuario pulsa una notificación para abrir la aplicación y mostrar los detalles de la notificación especificada.
  • Descartar acción: esta acción se envía a la aplicación cuando el usuario descarta una notificación determinada.

Las extensiones de contenido de notificación también tienen la capacidad de actualizar su interfaz de usuario cuando el usuario invoca una de las acciones personalizadas, como mostrar una fecha como aceptada cuando el usuario pulsa el botón Aceptar de acción personalizada. Además, las extensiones de contenido de notificación pueden indicar al sistema que retrase el descarte de la interfaz de usuario de notificación para que el usuario pueda ver el efecto de su acción antes de cerrar la notificación.

Para ello, se implementa una segunda versión del método DidReceiveNotification que incluye un controlador de finalización. Por ejemplo:

using System;
using Foundation;
using UIKit;
using UserNotifications;
using UserNotificationsUI;
using CoreGraphics;

namespace myApp {
    public class NotificationViewController : UIViewController, UNNotificationContentExtension {

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

            // Adjust the size of the content area
            var size = View.Bounds.Size
            PreferredContentSize = new CGSize(size.Width, size.Width/2);
        }

        public void DidReceiveNotification(UNNotification notification) {

            // Grab content
            var content = notification.Request.Content;

            // Display content in the UILabels
            EventTitle.Text = content.Title;
            EventDate.Text = content.Subtitle;
            EventMessage.Text = content.Body;

            // Get location and display
            var location = Content.UserInfo["location"] as string;
            if (location != null) {
                Event.Location.Text = location;
            }

            // Get Media Attachment
            if (content.Attachements.Length > 1) {
                var attachment = content.Attachments[0];
                if (attachment.Url.StartAccessingSecurityScopedResource()) {
                    EventImage.Image = UIImage.FromFile(attachment.Url.Path);
                    attachment.Url.StopAccessingSecurityScopedResource();
                }
            }
        }

        [Export ("didReceiveNotificationResponse:completionHandler:")]
        public void DidReceiveNotification (UNNotificationResponse response, Action<UNNotificationContentExtensionResponseOption> completionHandler)
        {

            // Update UI when the user interacts with the
            // Notification
            Server.PostEventResponse += (response) {
                // Take action based on the response
                switch(response.ActionIdentifier){
                case "accept":
                    EventResponse.Text = "Going!";
                    EventResponse.TextColor = UIColor.Green;
                    break;
                case "decline":
                    EventResponse.Text = "Not Going.";
                    EventResponse.TextColor = UIColor.Red;
                    break;
                }

                // Close Notification
                completionHandler (UNNotificationContentExtensionResponseOption.Dismiss);
            };
        }
    }
}

Al agregar el controlador de Server.PostEventResponse al método DidReceiveNotification de la extensión de contenido de notificación, la extensión debe controlar todas las acciones personalizadas. La extensión también puede reenviar las acciones personalizadas a la aplicación contenedora cambiando el UNNotificationContentExtensionResponseOption. Por ejemplo:

// Close Notification
completionHandler (UNNotificationContentExtensionResponseOption.DismissAndForwardAction);

Trabajar con la acción de entrada de texto en la interfaz de usuario personalizada

Según el diseño de la aplicación y la notificación, puede haber ocasiones que requieran que el usuario escriba texto en la notificación (por ejemplo, responder a un mensaje). Una extensión de contenido de notificación tiene acceso a la acción de entrada de texto integrada como lo hace una notificación estándar.

Por ejemplo:

using System;
using Foundation;
using UIKit;
using UserNotifications;
using UserNotificationsUI;

namespace MonkeyChatNotifyExtension
{
    public partial class NotificationViewController : UIViewController, IUNNotificationContentExtension
    {
        #region Computed Properties
        // Allow to take input
        public override bool CanBecomeFirstResponder {
            get { return true; }
        }

        // Return the custom created text input view with the
        // required buttons and return here
        public override UIView InputAccessoryView {
            get { return InputView; }
        }
        #endregion

        #region Constructors
        protected NotificationViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }
        #endregion

        #region Private Methods
        private UNNotificationCategory MakeExtensionCategory ()
        {

            // Create Accept Action
            ...

            // Create decline Action
            ...

            // Create Text Input Action
            var commentID = "comment";
            var commentTitle = "Comment";
            var textInputButtonTitle = "Send";
            var textInputPlaceholder = "Enter comment here...";
            var commentAction = UNTextInputNotificationAction.FromIdentifier (commentID, commentTitle, UNNotificationActionOptions.None, textInputButtonTitle, textInputPlaceholder);

            // Create category
            var categoryID = "event-invite";
            var actions = new UNNotificationAction [] { acceptAction, declineAction, commentAction };
            var intentIDs = new string [] { };
            var category = UNNotificationCategory.FromIdentifier (categoryID, actions, intentIDs, UNNotificationCategoryOptions.None);

            // Return new category
            return category;

        }
        #endregion

        #region Public Methods
        [Export ("didReceiveNotification:")]
        public void DidReceiveNotification (UNNotification notification)
        {
            label.Text = notification.Request.Content.Body;

            // Grab content
            var content = notification.Request.Content;

            // Display content in the UILabels
            EventTitle.Text = content.Title;
            EventDate.Text = content.Subtitle;
            EventMessage.Text = content.Body;

            // Get location and display
            var location = content.UserInfo ["location"].ToString ();
            if (location != null) {
                Event.Location.Text = location;
            }

            // Get Media Attachment
            if (content.Attachements.Length > 1) {
                var attachment = content.Attachments [0];
                if (attachment.Url.StartAccessingSecurityScopedResource ()) {
                    EventImage.Image = UIImage.FromFile (attachment.Url.Path);
                    attachment.Url.StopAccessingSecurityScopedResource ();
                }
            }
        }

        [Export ("didReceiveNotificationResponse:completionHandler:")]
        public void DidReceiveNotification (UNNotificationResponse response, Action<UNNotificationContentExtensionResponseOption> completionHandler)
        {

            // Is text input?
            if (response is UNTextInputNotificationResponse) {
                var textResponse = response as UNTextInputNotificationResponse;
                Server.Send (textResponse.UserText, () => {
                    // Close Notification
                    completionHandler (UNNotificationContentExtensionResponseOption.Dismiss);
                });
            }

            // Update UI when the user interacts with the
            // Notification
            Server.PostEventResponse += (response) {
                // Take action based on the response
                switch (response.ActionIdentifier) {
                case "accept":
                    EventResponse.Text = "Going!";
                    EventResponse.TextColor = UIColor.Green;
                    break;
                case "decline":
                    EventResponse.Text = "Not Going.";
                    EventResponse.TextColor = UIColor.Red;
                    break;
                }

                // Close Notification
                completionHandler (UNNotificationContentExtensionResponseOption.Dismiss);
            };
        }
        #endregion
    }
}

Este código crea una nueva acción de entrada de texto y la agrega a la categoría de la extensión (en el método MakeExtensionCategory). En el método de invalidación DidReceive, controla el usuario que escribe texto con el código siguiente:

// Is text input?
if (response is UNTextInputNotificationResponse) {
    var textResponse = response as UNTextInputNotificationResponse;
    Server.Send (textResponse.UserText, () => {
        // Close Notification
        completionHandler (UNNotificationContentExtensionResponseOption.Dismiss);
    });
}

Si el diseño necesita agregar botones personalizados al campo entrada de texto, agregue el código siguiente para incluirlos:

// Allow to take input
public override bool CanBecomeFirstResponder {
    get {return true;}
}

// Return the custom created text input view with the
// required buttons and return here
public override UIView InputAccessoryView {
    get {return InputView;}
}

Cuando el usuario desencadena la acción de comentario, es necesario activar el controlador de vista y el campo de entrada de texto personalizado:

// Update UI when the user interacts with the
// Notification
Server.PostEventResponse += (response) {
    // Take action based on the response
    switch(response.ActionIdentifier){
    ...
    case "comment":
        BecomeFirstResponder();
        TextField.BecomeFirstResponder();
        break;
    }

    // Close Notification
    completionHandler (UNNotificationContentExtensionResponseOption.Dismiss);

};

Resumen

En este artículo se ha echado un vistazo en profundidad al uso del nuevo marco de notificaciones de usuario en una aplicación de Xamarin.iOS. Se ha tratado la adición de datos adjuntos multimedia a notificaciones locales y remotas y se ha tratado el uso de la nueva interfaz de usuario de notificación para crear interfaces de usuario personalizadas.