Declare: usar API nativas iOS en tus apps

El framework de Xojo cuenta por omisión en su librería de iOS con una buena cantidad de controles listos para usar, así como de un nutrido conjunto de clases que facilitan el desarrollo nativo de nuestras aplicaciones tanto para iPhone como iPad. No obstante, en más de una ocasión querrás utilizar cualquiera de las API nativas Cocoa Touch y en el siguiente artículo verás como puedes hacerlo con el uso de Declare. Esta es una traducción al castellano del documento original que puedes encontrar en el área de desarrolladores de la web de Xojo.

Puedes llamar a las API de Cocoa Touch mediante el comando Declare para utilizar los métodos y las propiedades que no están incluidas de serie en el framework. Para crear una instrucción Declare necesitas en primer lugar obtener información sobre la API que quieres utilizar, empleando para ello la documentación de Apple: Apple Developer Documentation. La mayoría del tiempo utilizarás las librerias Foundation y UIKit, pero también hay otras librerías. Los Declares de Xojo utilizan los nombres de Objective-C, de modo que has de asegurarte de referirte a ellos en la documentación, en vez de fijarte en los nombres de Swift.

Cuando invocas los métodos Cocoa has de proporcionar el nombre del método usando el Selector en el comando Declare. El nombre del selector termina con el caracter “:” en el caso de que haya que pasarle parámetros. A diferencia de lo que ocurre con los métodos de Xojo, también es preciso contemplar el uso de mayúsculas y minúsculas. Para el Declare de Xojo el primer parámetro siempre es obligatorio, y se corresponde con una referencia a la clase que contiene el método que vas a llamar.

Dar el foco a un TextField

Para comenzar con un ejemplo sencillo, pongamos por caso que quieres definir el foco en un control de texto como es el caso de iOSTextField. Xojo no proporciona un método para ello. Buscando en el resumen de la página sobre iOSTextField verás que el control real de UIKit es UITextField. Haz clic sobre el enlace para abrir la página de documentación en la web de Apple. En la página de documentación de Apple encontrarás la información sobre llamar en primer lugar a becomeFirstResponder para mostrar el teclado, lo cual ocurre cuando el campo de texto obtiene el foco. Cuando haces clic sobre becomeFirstResponder irás a su página de documentación para ver la siguiente declaración:

(BOOL)becomeFirstResponder;

Lo anterior es el código Objective-C que indica que esta es una función que devuelve un valor booleano. También deberías de advertir en la página que este forma parte de la librería UIKit. Con esta información puedes crear ahora el comando Declare de Xojo para invocarlo:

Declare Function becomeFirstResponder Lib "UIKit" Selector "becomeFirstResponder" (controlHandle As Ptr) As Boolean

Lo importante aquí es advertir que siempre tienes un parámetro (el primer parámetro) que es una referencia a la instancia de la clase (o control en este caso).

Puedes llamara a este método tal y como harías con cualquier otro método Xojo, pero recuerda que has de pasarle una referencia al control. Asumiendo que tienes un control denominado TextField1 en la vista, puedes llamar a este método así:

Call becomeFirstResponder(TextField1.Handle)

El comando Call se utiliza para ignorar el valor devuelto, dado que en este caso es irrelevante

Si quieres utilizar esta función a menudo, entonces puedes definirla como un método de Extensión de clase, de modo que esté disponible para la clase propiamente dicha. Para ello, crea un módulo y añade un método global con la siguiente declaración:

SetFocus(Extends c As iOSTextField) As Boolean

En el método, añade el código Declare de la siguiente forma:

Declare Function becomeFirstResponder Lib "UIKit" Selector "becomeFirstResponder" (controlHandle As Ptr) As Boolean
Return becomeFirstResponder(c.Handle)

Ahora puedes llamar al método así:

Call TextField1.SetFocus

Usar el Portapapeles

Como ejemplo más avanzado, este es el modo en el que puedes añadir texto al portapapeles del sistema. En iOS el portapapeles se denomina portapapeles y está gestionado por la clase UIPasteboard. Buscando en la documentación de Apple por UIPasteboard, verás dos métodos que son útiles. El primero de ellos es el método compartido (o método de clase) generalPasteboard, y mediante el cual se obtiene una instancia del portapapeles del sistema. El otro método es setValue y que se emplea para depositar contenido, como por ejemplo texto, en el portapapeles.

Para empezar, crea en Xojo un método público en el objeto App y llámalo AddTextToPasteboard con esta declaración:

AddTextToPasteboard(value As Text)

La primera porción de código que necesitas es obtener una referencia a la clase UIPasteboard y llamar entonces al método generalPasteboard para obtener una instancia del UIPasteboard del sistema.

Para ello, tendrás que utiliar una función de utilidad común, NSClassFromString, mediante la cual se obtiene una referencia a la clase de iOS. De modo que esta será la primera línea de código:

Declare Function NSClassFromString Lib "Foundation" (className As CFStringRef) As Ptr

Ahora puedes utilizar esta función para obtener una referencia a la clase UIPasteboard:

Dim uiPasteboardClass As Ptr = NSClassFromString("UIPasteboard")

A continuación puedes llamar al método generalPasteboard pasándole la referencia de la clase UIPasteboard (UIPasteboard pertenece a la librería UIKit):

Declare Function generalPasteboard Lib "UIKit" Selector "generalPasteboard" (classRef As Ptr) As Ptr

Como referencia, esta es la declaración para el método setValue en los documentos de Apple:

- (void)setValue:(id)value forPasteboardType:(NSString *)pasteboardType;

Esta declaración te indica que el método es una Subrutina (el void inicial indica que no se devulve ningún valor) y que toma dos parámetros: value y passteboardType (como texto). Dado que este ejemplo es para poner el texto en el portapapeles, el método setValue puede mapearse a un comando Declare de Xojo de la siguiente forma:

Declare Sub setValue Lib "UIKit" Selector "setValue:forPasteboardType:" (pasteboardReference As Ptr, value As CFStringRef,
pasteboardType As CFStringRef)

Recuerda, el primer parámetro siempre es una referencia a la clase, y que se corresponde con el portapapeles en este caso. Otro aspecto a tener en cuenta es que el nombre del selector no es sólo el nombre del método setValue. Objective-C utiliza nombres que incluyen el parámetro, de modo que el selector se llama en realidad setValue:forPasteboardType(la variante correcta es importante). Este es el nombre completo que verás en la página de documentación de Apple para el método. Por último, cuando veas unaNSStringcomo tipo de Objective-C, puedes sustituirlo directamente con el tipo de XojoCFStringRef y que se encargará de convertir automáticamente el valor de Text al tipo correcto necesario para el Declare.

Con este Declare resuelto, ahora puedes llamar al método para incluir el texto en el portapapeles:

setValue(generalPasteboard(NSClassFromString("UIPasteboard")), value, "public.text")

La parte pasteboardType requiere un UTI que para el texto es “public.text”.

Combinando todo lo anterior, resulta en el siguiente método:

Public Sub AddTextToPasteboard(value As Text)
' Obtén una referencia al portapapeles del sistema
Declare Function NSClassFromString Lib "Foundation" (className As CFStringRef) As Ptr
Dim uiPasteboardClass As Ptr = NSClassFromString("UIPasteboard")
Declare Function generalPasteboard Lib "UIKit" Selector "generalPasteboard" (classRef As Ptr) As Ptr
Dim pasteboard As Ptr = generalPasteboard(uiPasteboardClass)
' Deposita el valor en el portapapeles
Declare Sub setValue Lib "UIKit" Selector "setValue:forPasteboardType:" (pasteboardReference As Ptr, value As CFStringRef,
pasteboardType As CFStringRef)
setValue(generalPasteboard(NSClassFromString("UIPasteboard")), value, "public.text")
End Sub

Ahora puedes usar tu nuevo método para incorporar texto en el portapapeles con este código:

App.AddTextToPasteboard(TextField1.Text)

Métodos de Utilidad

Como referencia, estas dos funciones de utilidad se emplean con frecuencia en los Declares. Ya has visto como emplear NSClassFromString. El m´todo alloc se puede utilizar para crear una nueva instancia de una clase cuando no hay un método de clase que devuelva una instancia. Es el equivalente a usar New en una clase Xojo.

' Obtiene una referencia a una clase iOS
Declare Function NSClassFromString Lib "Foundation" (classname As CFStringRef) As Ptr
' Uso: Dim NSClass As Ptr = NSClassFromString("NSClassName")
' Obtiene una instancia de una clase iOS
Declare Function alloc Lib "Foundation" Selector "alloc" (classRef As Ptr) As Ptr
' Uso: Dim instance As Ptr = alloc(NSClass)
Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *