1. Code
  2. Mobile Development
  3. iOS Development

iOS sucintamente: Aplicaciones multiescena

Scroll to top
This post is part of a series called iOS Succinctly.
iOS Succinctly - Hello, iOS!
iOS Succinctly - Asset Management

Spanish (Español) translation by Juliana Carvajal (you can also view the original English article)

El capítulo anterior presentó el flujo de trabajo básico del desarrollo de aplicaciones iOS, pero trabajamos dentro de los límites de una aplicación de vista única. Sin embargo, la mayoría de las aplicaciones del mundo real requieren varias escenas para presentar los datos de forma jerárquica. Si bien existen muchos tipos de patrones organizativos que se utilizan para administrar aplicaciones de múltiples escenas, este capítulo analiza uno de los patrones más comunes: la aplicación maestro-detalle.

La aplicación de mínimo detalle maestro consiste en una escena "maestra", que presenta una lista de elementos de datos para elegir, y una escena "detalle", que muestra los detalles de un elemento cuando el usuario lo selecciona de la escena maestra. Abre la aplicación Correo en tu iPhone y encontrarás un buen ejemplo de una aplicación de detalles maestros. La bandeja de entrada enumera tus mensajes, convirtiéndola en la escena principal, y cuando seleccionas uno de ellos, se utiliza una escena detallada para mostrar el contenido del mensaje, el remitente, los archivos adjuntos, etc.

En su mayor parte, las aplicaciones de múltiples escenas utilizan el mismo flujo de trabajo que se discutió en el capítulo anterior. Seguiremos creando diseños agregando componentes de IU a través de Constructor de interfaces y los conectaremos a nuestro código con acciones, salidas y delegados. Sin embargo, tener varias escenas significa que tendremos varios controladores de vista, por lo que tendremos que usar la nueva clase UINavigationController para organizar tu interacción. También aprenderemos a configurar las transiciones de escena mediante segues.


Creación de un proyecto de detalle maestro

El proyecto de ejemplo para este capítulo será una lista de contactos simple que permite a los usuarios administrar una lista de tus amigos, junto con tu información de contacto respectiva. Para crear el proyecto de ejemplo, selecciona Archivo > Nuevo > Proyecto y elige la Aplicación Maestro-Detalle. Esto nos dará la oportunidad de explorar nuevos componentes de navegación y estructuras organizativas, así como también cómo manejar las transiciones de una escena a otra.

tutorial_imageFigura 31: Creación de una plantilla de aplicación Maestro-Detalle

Utiliza Lista de amigos para el campo Nombre del producto, lo que desees para el Nombre de la organización y edu.self para el Identificador de la empresa. Al igual que la aplicación anterior, asegúrate de que iPhone sea el dispositivo seleccionado y usa Guiones gráficos y Utiliza recuento de referencia automático está seleccionado:

tutorial_imagetutorial_imagetutorial_imageFigura 32: Configurando el proyecto

Puedes guardar el proyecto donde quieras.


Descripción general de la plantilla

Nos basaremos en el código existente de la plantilla, así que echemos un vistazo rápido a la aplicación predeterminada. Haz clic en el botón Ejecutar en la esquina superior izquierda de Xcode o presiona Cmd+R para compilar la aplicación e iniciarla en el Simulador de iOS. Deberías ver una lista vacía titulada Maestro con un botón Editar y un botón Agregar (un signo más) en la barra de navegación. Al hacer clic en el botón Agregar, se insertará un nuevo elemento en la lista y, al seleccionarlo, se pasará a la escena de detalles. Ambas escenas se muestran en la siguiente figura.

tutorial_imagetutorial_imagetutorial_imagetutorial_imagetutorial_imagetutorial_imageFigura 33: Escenas maestras y detalladas predeterminadas de la plantilla

Los elementos de datos predeterminados utilizados por la plantilla son las fechas, pero vamos a cambiar la escena maestra para mostrar una lista de nombres y la escena de detalles para mostrar tu información de contacto.

Discutiremos los detalles detrás de cada archivo fuente a medida que construimos el proyecto de ejemplo, pero será útil tener una descripción general básica de las clases predeterminadas antes de comenzar a editarlas.

El delegado de la aplicación

Como en el capítulo anterior, la clase AppDelegate te permite reaccionar ante eventos importantes en el ciclo de vida de la aplicación. No necesitamos ningún comportamiento de inicio personalizado para nuestra aplicación de lista de amigos, por lo que no editaremos esta clase en absoluto.

Los controladores de vista

En lugar de un solo ViewController, esta plantilla tiene dos clases de controlador de vista: un MasterViewController y un DetailViewController. Estos administran la escena maestra y la escena detallada, y tus métodos viewDidLoad sirven como punto de entrada a tus respectivas escenas. El método viewDidLoad de MasterViewController debería tener el siguiente aspecto:

1
- (void)viewDidLoad {
2
    [super viewDidLoad];
3
    self.navigationItem.leftBarButtonItem = self.editButtonItem;
4
5
    UIBarButtonItem *addButton = [[UIBarButtonItem alloc]                       
6
        initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
7
                             target:self                                
8
                             action:@selector(insertNewObject:)];
9
    self.navigationItem.rightBarButtonItem = addButton;
10
}

Esto crea los botones Editar y Agregar que ves en la parte superior de la escena maestra, y establece el método insertNewObject: como la acción para este último. El método insertNewObject: agrega una nueva instancia NSDate a la variable privada _objects, que es una matriz mutable que contiene la lista maestra de elementos de datos, y todos los métodos después de la marca #pragma - La directiva Vista de tabla controla cómo se muestra esa lista en la escena. Se llama al método prepareForSegue: sender: antes de pasar a la escena de detalle, y es donde se transfiere la información necesaria de la escena maestra a la escena de detalle.

La clase DetailViewController es un poco más simple. Simplemente declara una propiedad detailItem para almacenar el elemento seleccionado y lo muestra a través de la salida detailDescriptionLabel. Vamos a cambiar esta implementación predeterminada para mostrar la información de contacto de una persona.

El guión gráfico

El guión gráfico es quizás el cambio más drástico del ejemplo anterior. Si abres MainStoryboard.storyboard, deberías ver lo siguiente:

tutorial_imagetutorial_imagetutorial_imageFigura 34: Guión gráfico predeterminado de la plantilla

En lugar de un controlador de vista único, Constructor de interfaces ahora administra tres controladores. Esto puede parecer extraño considerando que nuestra aplicación solo tiene dos escenas, pero tanto MasterViewController como DetailViewController están incrustados en una instancia de UINavigationController. Este controlador de navegación es la razón por la que vemos una barra de navegación en la parte superior de la aplicación, y es lo que nos permite navegar hacia adelante y hacia atrás entre las escenas maestra y detallada. Hablaremos más sobre la configuración de los controladores de navegación a lo largo del capítulo.

Esta plantilla también debe aclarar por qué el archivo MainStoryboard.storyboard se llama "guión gráfico": visualiza no solo las escenas en sí, sino el flujo entre esas escenas. Como en el capítulo anterior, la flecha que apunta al controlador de navegación muestra que es el controlador raíz. Pero también vemos otra flecha del controlador de navegación al MasterViewController y del MasterViewController al DetailViewController. Estas flechas definen las relaciones y transiciones entre todos los controladores de vista de una aplicación.


Los datos del modelo

A diferencia del capítulo anterior, esta aplicación utilizará una clase dedicada para representar los datos de tu modelo. Usaremos la clase Persona para almacenar la información de contacto de cada amigo. En Xcode, crea un nuevo archivo, selecciona la clase Objective-C e ingresa Persona para el campo Clase, así:

tutorial_imagetutorial_imagetutorial_imageFigura 35: Creando la clase Persona

A continuación, debemos declarar algunas propiedades para registrar el nombre, la organización y el número de teléfono de cada contacto. Abre Person.h y cámbialo a lo siguiente:

1
#import <Foundation/Foundation.h>
2
3
@interface Person : NSObject
4
5
@property (copy, nonatomic) NSString *firstName;
6
@property (copy, nonatomic) NSString *lastName;
7
@property (copy, nonatomic) NSString *organization;
8
@property (copy, nonatomic) NSString *phoneNumber;
9
10
@end

Por supuesto, también necesitamos sintetizar estas propiedades en Person.m.

1
#import "Person.h"
2
3
@implementation Person
4
5
@synthesize firstName = _firstName;
6
@synthesize lastName = _lastName;
7
@synthesize organization = _organization;
8
@synthesize phoneNumber = _phoneNumber;
9
10
@end

Eso es todo lo que necesitamos para representar los datos detrás de nuestra aplicación. Las instancias de esta clase se pasarán entre las escenas MasterViewController y DetailViewController, que las mostrarán utilizando varios componentes de la interfaz de usuario.


La escena maestra

A continuación, configuraremos la escena maestra para mostrar una lista de objetos Persona. Definir el comportamiento de una escena requiere una interacción cuidadosa entre el código fuente del controlador de vista subyacente y la representación visual en Constructor de interfaces. Antes de realizar cualquier codificación, echemos un vistazo más de cerca a la escena maestra de la plantilla en el guión gráfico.

Relaciones

En nuestro guión gráfico, una relación define la conexión entre un controlador de navegación y otra escena. El Constructor de interfaces visualiza la relación como una flecha desde el controlador de navegación a la otra escena con un icono de enlace encima. Al seleccionar este icono, se resaltará el controlador de navegación, como se muestra en la siguiente captura de pantalla:

tutorial_imagetutorial_imagetutorial_imageFigura 36: La relación entre el controlador de navegación raíz y el controlador de vista principal

La plantilla estableció esta relación para nosotros, pero es importante que puedas configurarla tu mismo. Entonces, continúa y elimina el controlador de navegación seleccionándolo y presionando Eliminar. Para volver a crear la relación, selecciona el icono amarillo del Controlador de vista en el controlador de vista principal y luego navega hasta Editor en la barra de menú de Xcode y selecciona Insertar en > Controlador de navegación. Debería aparecer un nuevo controlador de navegación y volver al punto de partida.

Es importante comprender que la flecha de relación no significa una transición entre el controlador de navegación y el controlador maestro. Más bien, incrustar nuestra escena maestra en un controlador de navegación de esta manera crea una jerarquía de controlador de vista. Dice que la escena maestra pertenece al controlador de navegación. Esto hace posible cambiar entre escenas usando los botones de navegación y transiciones incorporados del controlador de navegación. Por ejemplo, el controlador de navegación agrega automáticamente el botón Maestro que aparece en la parte superior de la escena de detalles:

tutorial_imageFigura 37: El botón de navegación integrado proporcionado por el controlador de navegación

La funcionalidad incorporada para cambiar entre escenas hace que los controladores de navegación sean una manera fácil de configurar el flujo de aplicaciones complejas. La siguiente sección analiza cómo definir las transiciones entre las escenas de un controlador de navegación.

Segues

Un segue representa una transición de una escena a otra. Al igual que las relaciones, se visualiza como una flecha desde la escena de origen a la escena de destino, pero utiliza un icono diferente. Observa que cuando haces clic en el icono de segue, solo se resalta una celda de la tabla. Esto nos dice que el segue se adjunta a celdas de tabla individuales en lugar de a toda la escena maestra.

tutorial_imagetutorial_imagetutorial_imageFigura 38: La transición de empuje de la escena maestra a la escena de detalle

Nuevamente, nuestra plantilla creó esta transición para nosotros, pero es importante poder crear una desde cero. Por lo tanto, selecciona el icono de segue y presiona Eliminar para eliminarlo del guión gráfico. Para volver a crearlo, mantén presionada la tecla Control y arrastra desde la celda de la tabla hasta la escena de detalle.

tutorial_imagetutorial_imagetutorial_imageFigura 39: Control y arrastre desde la celda de la tabla maestra a la escena de detalle

Esto abrirá un menú que te pedirá el tipo de acción de accesorio/secuencia de selección. Queremos que nuestra transición se produzca cuando el usuario seleccione la celda de la tabla, así que elige presionar en el grupo Selección de secuencia.

tutorial_imageFigura 40: Selecciona el tipo de segue para crear

El UINavigationController principal administra tus escenas a través de una pila de navegación, y tus métodos pushViewController:animated: y popViewControllerAnimated: te permiten agregar o eliminar instancias de controlador de vista de la pila. Por ejemplo, empujar un objeto de controlador de vista de detalle en la pila de navegación es la forma en que se profundiza en la escena de detalle, y al hacer clic en el botón Maestro en la barra de navegación de la escena de detalle, aparece de la pila de navegación. Selecciona push en el menú de la Figura 40 le dice al segue que llame al método pushViewController:animated: para hacer la transición de la escena maestra a la escena detallada.

Además de un tipo, cada segue también debe tener un identificador único para que se pueda acceder a él desde su código fuente. Puedes editar la ID de una segue seleccionando el icono de segue y abriendo el panel de inspección de atributos. Nuestro segue debe tener un identificador de showDetail, y también deberías ver el tipo Push segue en el campo Estilo:

tutorial_imageFigura 41: El inspector de atributos para la segue maestro-detalle

La otra opción de estilo es modal, que presenta otra escena sobre una escena existente, completamente independiente del controlador de navegación principal. Debes dejar el estilo de esta segue como Push (crearemos una segue modal hacia el final de este capítulo).

Mesas

Una de las principales diferencias entre nuestra escena maestra y ViewController del capítulo anterior es el hecho de que hereda de UITableViewController en lugar de UIViewController. Un controlador de vista de tabla administra una instancia de UITableView. Las vistas de tabla se componen de una sola columna de filas, posiblemente agrupadas en secciones. Esto los hace muy adecuados para presentar listas de datos.

Dado que las vistas de tabla son contenedores gráficos, puede resultar difícil seleccionarlas en el editor de escenas. La forma más sencilla de seleccionarlo es desde el esquema del documento a la izquierda del editor de escenas. El esquema del documento es un árbol que contiene todos los elementos administrados por el Constructor de interfaces, y debes encontrar un elemento de Vista de tabla debajo del Controlador de vista principal, como se muestra en la siguiente figura.

tutorial_imageFigura 42: Selecciona la instancia de UITableView del esquema del documento

Cuando seleccionas la vista de tabla, todo lo que se encuentra debajo de la barra de navegación en la escena maestra debe resaltarse en el generador de escenas. Esto te da la oportunidad de editar las propiedades de la vista de tabla en el inspector de atributos. La opción más importante es el campo Contenido, que determina cómo interactuará con la tabla desde tu código:

tutorial_imageFigura 43: El inspector de atributos para la vista de tabla de la escena maestra

Si configuras el campo Contenido en Prototipos dinámicos, puedes crear nuevas celdas duplicando una celda prototípica diseñada en Constructor de interfaces. Las celdas estáticas, por otro lado, no se pueden duplicar, lo que da como resultado una tabla estática. Esto significa que debes usar prototipos dinámicos cuando desees insertar o eliminar filas sobre la marcha, y usar celdas estáticas cuando tu tabla siempre muestre la misma cantidad de información. Mantén dinámica la mesa de la escena maestra. Usaremos una tabla estática para la escena detallada.

Cuando usas celdas de prototipo, debes darle a cada prototipo un identificador único para que se pueda acceder a él desde tu código fuente (como una ID de segue). Para editar la ID de una celda de prototipo, selecciona la celda en el editor de escenas o en el generador de interfaces y abra el inspector de atributos. El identificador para ese prototipo en particular se puede establecer en el campo Identificador, como se muestra en la siguiente figura. Dado que solo vamos a tener una celda prototípica en esta aplicación, puedes dejar el valor de celda predeterminado, pero para aplicaciones reales debes darle a cada prototipo un identificador descriptivo.

tutorial_imageFigura 44: El inspector de atributos para la celda de la tabla del prototipo

También vale la pena echar un vistazo al inspector de conexiones para UITableView (no la celda prototipo). Deberías ver una fuente de datos y una salida delegada, y ambos deben especificar la clase MasterViewController para tu destino.

tutorial_imageFigura 45: Las conexiones de salida para la vista de tabla de la escena maestra

La fuente de datos de una vista de tabla es un tipo especial de delegado que proporciona la información para cada fila de la tabla. Además de los datos sin procesar, es necesario un delegado de vista de tabla para definir el comportamiento de la tabla y la apariencia de cada fila. Al igual que con los delegados de aplicaciones y campos de texto, estos se implementan a través de protocolos llamados UITableViewDataSource y UITableViewDelegate, respectivamente.

En este caso, la clase MasterViewController actúa como fuente de datos y como delegado, por lo que la plantilla maestro-detalle incluía métodos como tableView:cellForRowAtIndexPath: y tableView:canEditRowAtIndexPath: en MasterViewController.m. En la siguiente sección, modificaremos estos métodos para cambiar la apariencia de la lista de amigos.

Codificación del controlador de vista principal

Ahora que tenemos un mejor control de lo que está sucediendo en el guión gráfico, estamos listos para comenzar a personalizar nuestra clase MasterViewController. En este momento, la escena maestra muestra una lista de objetos NSDate, pero queremos cambiarlos a objetos Persona. Por supuesto, esto significa que necesitaremos acceso a la clase Persona, así que importa el encabezado en MasterViewController.m:

1
#import "Person.h"

Recuerda que el método viewDidLoad: le dice al botón Agregar de la escena maestra que llame al método insertNewObject: cada vez que el usuario lo toque. En lugar de agregar un objeto de fecha a la matriz _objects, necesitamos insertNewObject: para agregar un objeto Persona. Cámbialo a lo siguiente:

1
- (void)insertNewObject:(id)sender {
2
    if (!_objects) {
3
        _objects = [[NSMutableArray alloc] init];
4
    }
5
    Person *friend = [[Person alloc] init];
6
    friend.firstName = @"<First Name>";
7
    friend.lastName = @"<Last Name>";
8
    friend.organization = @"<Organization>";
9
    friend.phoneNumber = @"<Phone Number>";
10
    [_objects insertObject:friend atIndex:0];
11
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
12
    [self.tableView insertRowsAtIndexPaths:@[indexPath] 
13
                    withRowAnimation:UITableViewRowAnimationAutomatic];
14
}

Esto crea una instancia de un nuevo objeto Persona y lo llena con algunos valores ficticios, y luego lo agrega al frente de la matriz _objects con insertObject: atIndex:. La instancia de NSIndexPath es un objeto de datos simple que representa el índice de una celda en particular, y insertRowsAtIndexPaths:withRowAnimation: agrega una nueva celda en la ubicación especificada. Observa que este último método en realidad no crea la nueva celda, solo agrega un elemento a la matriz _objects y le dice a la tabla que debería tener una fila más. Esto solicita a la tabla que cree una nueva celda, que es preparada por el método de delegado de origen de datos tableView:cellForRowAtIndexPath: data source. Debería verse así:

1
- (UITableViewCell *)tableView:(UITableView *)tableView
2
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
3
    UITableViewCell *cell = [tableView
4
                             dequeueReusableCellWithIdentifier:@"Cell"
5
                             forIndexPath:indexPath];
6
    Person *friend = _objects[indexPath.row];
7
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",
8
                           friend.firstName, friend.lastName];
9
    return cell;
10
}

Este método se llama cada vez que la tabla necesita representar una celda determinada, y debe devolver un objeto UITableViewCell que represente la fila correspondiente. Primero, buscamos una celda prototipo usando el identificador definido en el guión gráfico, y luego usamos la instancia NSIndexPath para encontrar el objeto Persona asociado. Finalmente, mostramos el nombre de la persona a través de la propiedad textLabel de la celda.

Ahora, deberías poder agregar, ver y eliminar objetos Persona de la escena maestra:

tutorial_imagetutorial_imagetutorial_imageFigura 46: Agrega un objeto Persona a la escena maestra

Eso cubre la funcionalidad de lista básica para la escena maestra, pero todavía tenemos una tarea más antes de pasar a la escena de detalles. Cuando un usuario selecciona uno de los elementos de la lista maestra, debemos pasar ese objeto a la escena de detalles.

Recuerda que UINavigationController y push segue manejan la transición por nosotros, pero nos da la oportunidad de enviar datos desde el controlador de la vista de origen al controlador de la vista de destino llamando al método prepareForSegue:sender: justo antes de que cambies a la vista de detalles. Cambia prepareForSegue:sender: en MasterViewController.m a lo siguiente (el único cambio real es usar un objeto Persona en lugar de una instancia NSDate):

1
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
2
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
3
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
4
        Person *friend = _objects[indexPath.row];
5
        [[segue destinationViewController] setDetailItem:friend];
6
    }
7
}

Este método es cómo pasamos datos entre la escena maestra y la escena de detalle. Se llama para cada segue asociado con un controlador en particular, por lo que nuestro primer paso es verificar el ID de segue, que se definió en el Constructor de interfaces. Luego, usamos el método indexPathForSelectedRow para obtener el índice de la fila seleccionada (no son geniales las convenciones de nomenclatura de Objective-C), y usamos ese índice para encontrar el elemento de datos correspondiente de la matriz _objects. Finalmente, pasamos este objeto a la escena de detalle estableciendo su propiedad detailItem.

tutorial_imagetutorial_imagetutorial_imageFigura 47: Selecciona un objeto Persona de la escena maestra

Ahora, cuando selecciones un elemento de la lista maestra, deberías ver un objeto Persona en lugar de una instancia de NSDate. La escena de detalle predeterminada utiliza el método de descripción para convertir el objeto en una cadena, por lo que vemos una dirección de memoria en la Figura 47 en lugar de cualquier información significativa. Cambiaremos eso en la siguiente sección.

Para resumir nuestra escena maestra: tenemos una conexión de relación que la incrusta en una instancia de UINavigationController, un segue que define la transición a la escena de detalle, una celda prototipo que usamos como plantilla para las nuevas filas de la tabla, un botón Agregar que agrega instancias ficticias a la lista maestra de elementos de datos, y un método prepareForSegue:sender: que pasa el elemento seleccionado a la escena de detalles.


La escena de los detalles

A continuación, necesitamos configurar la escena de detalle para mostrar el amigo seleccionado. Un solo objeto Persona siempre tiene la misma cantidad de información (un nombre, una organización y un número de teléfono), por lo que usaremos tres celdas estáticas para formatear la salida en lugar de prototipos dinámicos. Al igual que en la escena maestra, primero configuraremos el Constructor de interfaces y luego codificaremos la funcionalidad después de que tengamos los componentes de la interfaz de usuario dispuestos.

Cambia a un controlador de vista de tabla

La plantilla maestro-detalle usa un ViewController simple para la escena de detalles, por lo que nuestra primera tarea es reemplazarlo con un UITableViewController. En el Constructor de interfaces, selecciona la escena detallada y presiona Eliminar para eliminarla del guión gráfico. Luego, arrastra un objeto Controlador de vista de tabla desde la Biblioteca de objetos al editor de escenas.

tutorial_imageFigura 48: El controlador de vista de tabla en la biblioteca de objetos

La transición se eliminó junto con la escena de detalle anterior, por lo que la nueva vista de tabla aún no forma parte de la jerarquía del controlador de navegación. Vuelve a crear la segue arrastrando desde la celda del prototipo de la escena maestra a la nueva escena de detalles y luego selecciona empujar para crear una segue de empuje. Después de eso, asegúrate de cambiar el ID del segue a showDetail.

tutorial_imagetutorial_imagetutorial_imageFigura 49: Recreación de la transición de empuje de la escena maestra a la escena de detalle

Esto integra el controlador de vista de tabla con la jerarquía de navegación, y el Constructor de interfaces lo refleja agregando una barra de navegación en la parte superior de la escena de detalles. Sin embargo, esa barra de navegación ahora está en blanco. Arreglemos eso haciendo doble clic en el centro de la barra de navegación vacía e ingresando Detalle como el título de la escena, así:

tutorial_imageFigura 50: Definición del título de la escena de detalle

También necesitamos conectar la nueva escena a nuestra clase DetailViewController. Antes de cambiar la clase en el generador de interfaces, debemos hacer que DetailViewController herede de UITableViewController. Cambia la declaración de interfaz en DetailViewController.h por lo siguiente:

1
@interface DetailViewController : UITableViewController

Luego, abre el guión gráfico nuevamente, selecciona el icono amarillo en el dock del Controlador de vista de tabla, abre el inspector de componentes y cambia la Clase a DetailViewController.

tutorial_imageFigura 51: Configuración de la nueva clase del controlador de vista de tabla

Ahora volvemos a donde comenzamos, pero tenemos un controlador de vista de tabla en lugar de un controlador de vista normal. Recuerda que vamos a utilizar una tabla estática para diseñar la información del objeto Persona seleccionado. Por lo tanto, selecciona la vista detallada de la escena detallada en el esquema del documento.

tutorial_imageFigura 52: Selección de la vista de tabla de la escena de detalle

Luego, cambia el campo Contenido a Celdas estáticas en el inspector de atributos. También puedes cambiar Separador a Ninguno y Selección a Sin selección. Esto elimina la línea entre las celdas y evita que los usuarios las seleccionen.

tutorial_imageFigura 53: Cambio del contenido de la Vista de tabla de prototipos dinámicos a celdas estáticas

Ahora deberías ver tres celdas en blanco en la escena de detalle. Para seleccionarlos todos, mantén presionada la tecla Mayús y haz clic en ellos, y luego cambia su Estilo a Detalle izquierdo en el inspector de atributos. Esto agrega un título y una etiqueta de detalle a cada una de las celdas. Cambia las etiquetas de título a Nombre, Teléfono y Organización para que tu escena de detalles se vea como la siguiente:

tutorial_imageFigura 54: Configuración de las etiquetas de título de las celdas estáticas

Después de agregar algunas propiedades a la clase DetailViewController, convertiremos las etiquetas de detalles restantes en puntos de venta y las usaremos para mostrar la información de la persona seleccionada.

Codificación del controlador de vista de detalles

Eso es todo lo que podemos hacer en el Constructor de interfaces por ahora. Agreguemos algunas propiedades a DetailViewController para que podamos acceder a las etiquetas de detalles que acabamos de agregar. Cambia DetailViewController.h por lo siguiente:

1
#import <UIKit/UIKit.h>
2
3
@interface DetailViewController : UITableViewController
4
5
@property (strong, nonatomic) id detailItem;
6
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
7
@property (weak, nonatomic) IBOutlet UILabel *organizationLabel;
8
@property (weak, nonatomic) IBOutlet UILabel *phoneNumberLabel;
9
10
@end

Recuerda del capítulo anterior que el modificador IBOutlet es lo que hace que estas propiedades estén disponibles para el Constructor de interfaces. A continuación, sintetiza estas propiedades en DetailViewController.m:

1
#import "DetailViewController.h"
2
#import "Person.h"
3
4
@implementation DetailViewController
5
6
@synthesize detailItem = _detailItem;
7
@synthesize nameLabel = _nameLabel;
8
@synthesize organizationLabel = _organizationLabel;
9
@synthesize phoneNumberLabel = _phoneNumberLabel;
10
Then, change the configureView method to set the value of the detail labels based on the Person object passed in from the master scene:
11
- (void)configureView {
12
    if (self.detailItem &&
13
        [self.detailItem isKindOfClass:[Person class]]) {
14
        NSString *name = [NSString stringWithFormat:@"%@ %@",
15
                          [self.detailItem firstName],
16
                          [self.detailItem lastName]];
17
        self.nameLabel.text = name;
18
        self.organizationLabel.text = [self.detailItem organization];
19
        self.phoneNumberLabel.text = [self.detailItem phoneNumber];
20
    }
21
}

También observa que usamos el método isKindOfClass: para asegurarnos de que el elemento de detalle es de hecho un objeto Persona. Este es un paso de mejores prácticas cuando se utilizan variables de tipo dinámico como detailItem.

Conexiones de salida

Nuestro último paso para la escena de detalles es conectar los campos nameLabel, organizationLabel y phoneNumberLabel a tus componentes UILabel correspondientes en el guión gráfico. Esto se puede lograr seleccionando el icono amarillo en el muelle de la escena de detalle y arrastrando desde los círculos en el inspector de Conexiones hasta los componentes de la etiqueta en el editor de escena. Asegúrate de arrastrar cada salida a las etiquetas correspondientes.

tutorial_imagetutorial_imagetutorial_imageFigura 55: Conexión de los componentes de la etiqueta al controlador de vista detallada

Cuando compiles la aplicación, deberías poder seleccionar elementos de la lista maestra y ver tus detalles en la escena de detalles. Ten en cuenta que solo podemos mostrar detalles; todavía no podemos editarlos.

tutorial_imagetutorial_imagetutorial_imageFigura 56: La escena de detalle completa

Para resumir los cambios en nuestra escena de detalle: reemplazamos el controlador predeterminado con un componente Controlador de vista de tabla, cambiamos DetailViewController para heredar de UITableViewController, recreamos la transición de la escena maestra a la escena de detalles y declaramos varias propiedades que sirvieron como salidas desde DetailViewController a instancias de UILabel. El objetivo de todo esto era mostrar las propiedades de la instancia de Persona que se seleccionó en la escena maestra.


El controlador de vista de edición

Nuestro trabajo final para este capítulo será agregar otra escena que nos permita editar el elemento seleccionado. En lugar de un segue push, vamos a implementar esta nueva escena utilizando un segue modal. Un segue modal presenta la escena de destino "encima" de la escena existente, como una ventana emergente en una computadora de escritorio. Esto no afecta la jerarquía de navegación, por lo que en lugar de que un UINavigationController principal asuma la responsabilidad de navegar entre las escenas, la escena presentada de forma modal se descarta a sí misma cuando es necesario.

Para nuestro ejemplo, agregaremos una transición modal entre nuestra escena de detalle existente y una nueva escena de edición, luego usaremos una transición de desenrollado para volver a la escena original. Esto nos brinda una nueva herramienta para controlar el flujo de nuestra aplicación, y también presenta la oportunidad de sentirnos un poco más cómodos con las barras de navegación.

Crea la escena de edición

Antes de que podamos crear un segue modal, necesitamos una escena de edición para trabajar. Esta escena funcionará casi exactamente como la escena de detalle, excepto que tendrá componentes UITextField en lugar de UILabels para que el usuario pueda editar cada propiedad. Primero, crea una nueva clase llamada EditViewController y usa UITableViewController para la superclase:

tutorial_imageFigura 57: Creación de la clase para el controlador de vista de edición

A continuación, abre Constructor de interfaces y arrastra otro controlador de vista de tabla desde la biblioteca de objetos al editor de escenas. Colócalo sobre la escena de detalle, así:

tutorial_imagetutorial_imagetutorial_imageFigura 58: Agrega un controlador de vista de tabla al guión gráfico

Este nuevo controlador debe estar conectado a la clase EditViewController que acabamos de crear, así que selecciónalo en el Editor de interfaz, abre el inspector de identidad y cambia el campo Clase a EditViewController.

tutorial_imageFigura 59: Definición de la clase del nuevo controlador de vista de tabla

Navegando a la escena de edición

Nuestra escena de edición utilizará una barra de navegación para presentar los botones Cancelar y Guardar. Podríamos incrustarlo en la raíz UINavigationController, pero recuerda que queremos presentarlo de manera modal, no empujándolo a la pila de controladores de vista existente. Para darle su propia barra de navegación, todo lo que tenemos que hacer es incrustarla en tu propio controlador de navegación. Selecciona Editar controlador de vista en Constructor de interfaces y selecciona Editor > Insertar en > Controlador de navegación en el menú Xcode.

tutorial_imagetutorial_imagetutorial_imageFigura 60: Incrustación de la escena de edición en un nuevo controlador de navegación

Mientras que los push segues permiten que el controlador de navegación que lo contiene agregue botones de navegación por ti, necesitamos agregar nuestros propios botones para el segue modal. La Estructura UIKit utiliza una categoría especial de controles para su uso en las barras de navegación. Estamos buscando un elemento de botón de barra, que puedes encontrar en la sección Ventanas y barras de la Biblioteca de objetos.

tutorial_imageFigura 61: El elemento del botón de la barra en la biblioteca de objetos

Arrastra un elemento de botón de barra de la biblioteca de objetos al lado derecho de la barra de navegación de la escena de detalle. Debería encajar en su lugar y tener un valor predeterminado de Elemento, como se muestra en la siguiente captura de pantalla:

tutorial_imageFigura 62: Agrega un botón de edición a la barra de navegación de la escena detallada

Este botón lanzará la escena de edición, por lo que probablemente deberíamos cambiar el texto a Editar. Puedes hacer esto cambiando manualmente el texto en el editor de escenas, pero la forma preferida es seleccionar uno de los tipos de botones predefinidos del inspector de atributos. Selecciona el elemento del botón de barra y cambia tu campo Identificador de Personalizado a Editar.

tutorial_imageFigura 63: Cambio del botón de la barra a un botón de edición

Estos tipos predefinidos te permiten acceder a los iconos del sistema predeterminados que brindan una experiencia de usuario consistente en todas las aplicaciones. Esto no es un gran problema para los botones Agregar, Editar, Listo y otros botones basados ​​en texto, pero puedes marcar una gran diferencia para los tipos de iconos como Redactar:

tutorial_imageFigura 64: Tipo de elemento del botón de la barra de redacción

A continuación, debemos realizar la transición de nuestro nuevo botón de edición a la escena de edición. Esto utiliza el mismo proceso que la transición de empuje desde la celda de la tabla maestra a la escena de detalle. Mantén presionada la tecla Control y arrastra desde el botón de edición hasta el nuevo controlador de navegación y selecciona Modal para la acción Segue. Deberías ver una nueva conexión segue con un icono modal en ella:

tutorial_imagetutorial_imagetutorial_imageFigura 65: Creando el segue modal

Como ocurre con todos los segues, nuestro nuevo segue modal necesita un identificador único. Selecciona el icono de segue modal e introduce editDetail en el campo Identificador del inspector de atributos. Ahora deberías poder compilar el proyecto (con algunas advertencias) y lanzar una escena de edición vacía tocando el botón Editar en la escena de detalles. Nuestra próxima tarea será agregar algunos componentes de la interfaz de usuario a la escena de edición, junto con un botón Cancelar y Guardar.

Diseña la escena de edición

A continuación, diseñaremos la escena de edición. Se parecerá mucho a la escena de detalles, excepto que tendrás campos de texto en lugar de etiquetas. Nuestra primera tarea es agregar un título a la barra de navegación. Haz doble clic en el centro de la barra de navegación de la escena de edición y escribe Editar. La escena debería verse así después:

tutorial_imageFigura 66: Agrega un título a la escena de edición

A continuación, debemos cambiar la vista de tabla de una tabla dinámica a una estática. Selecciona el objeto Vista de tabla de la escena de edición del Esquema del documento, como se muestra en la siguiente figura:

tutorial_imageFigura 67: Selecciona el objeto Vista de tabla

Luego, cambia el campo Contenido del inspector de atributos a Celdas estáticas. Elimina todas menos una de las celdas estáticas que aparecen en el editor de escenas. También es una buena idea cambiar el campo Selección a Sin selección, ya que solo usamos la tabla para fines de diseño.

Ahora, no podemos usar ninguno de los valores de Estilo predeterminados para las celdas, ya que ninguno de ellos usa campos de texto. En su lugar, crearemos la celda desde cero. Primero, arrastra un objeto Etiqueta y Campo de texto a la celda restante y usa las pautas para asegurarte de que estén centrados verticalmente. También debes cambiar el tamaño de la etiqueta y el campo de texto para que se parezcan a lo siguiente:

tutorial_imageFigura 68: Agrega una etiqueta y un campo de texto a la escena de edición

Para la escena de detalle, especificamos Detalle izquierdo para el Estilo de celda. Esto definió automáticamente el estilo, la fuente y la alineación de los componentes, pero como estamos creando una celda personalizada, debemos hacerlo nosotros mismos. Todas estas configuraciones se pueden definir en el inspector de atributos para los objetos UILabel y UITextField. Para la etiqueta, cambia el texto a Nombre y luego establece el mismo color que las etiquetas de título en la escena de detalles. Una forma de hacerlo es abrir el panel Colores para la etiqueta de la escena de edición, selecciona la lupa (que en realidad actúa más como un cuentagotas) y selecciona el color de la etiqueta del título de la escena de detalle. El color seleccionado debe ser el de la siguiente figura:

tutorial_imageFigura 69: La herramienta "cuentagotas" en el panel Colores

Finalmente, cambia la fuente a System Bold con un tamaño de 12 y cambia la alineación a Derecha. La configuración final se muestra en la siguiente captura de pantalla:

tutorial_imageFigura 70: Atributos finales de la etiqueta

Todo lo que necesitas hacer para el campo de texto es cambiar las mayúsculas a Palabras. Para crear las celdas para los otros campos, copia y pega la celda existente tres veces y cambia tus etiquetas a Apellido, Teléfono y Organización. Esto te dará la siguiente tabla:

tutorial_imageFigura 71: Las celdas de la tabla de escenas de edición con las etiquetas adecuadas

También debes cambiar el campo Teclado para el campo de texto Teléfono a Teclado numérico para mostrar un teclado numérico en lugar de un teclado QWERTY. Eso cubre la tabla de la escena de edición, pero si intentas compilar el proyecto ahora mismo, notarás que todas estas celdas desaparecen. Esto se debe a que EditViewController.m proporcionado por la plantilla de clase define varios métodos de fuente de datos que tratan la tabla como una celda prototipo. Los eliminaremos en la siguiente sección.

Pero antes de hacerlo, agreguemos dos botones a la barra de navegación para que los usuarios puedan elegir si desean cancelar o guardar sus ediciones. Arrastra dos elementos de botón de barra de la biblioteca de objetos a cada lado de la barra de navegación. Cambia el campo Identificador del botón izquierdo a Cancelar y el de la derecha a Guardar.

tutorial_imageFigura 72: El diseño completo para la escena de edición

Observa cómo el botón Guardar es de color azul brillante según las convenciones de UX de iOS. Una vez más, estos identificadores predeterminados ayudan a garantizar una interfaz de usuario coherente en todas las aplicaciones.

Codificación del controlador de vista de edición

En esta sección, codificaremos la funcionalidad detrás de los componentes de la interfaz de usuario que acabamos de agregar al guión gráfico. Las dos tareas principales son preparar salidas para los campos de texto para que podamos acceder a ellos desde la clase EditViewController e implementar un delegado de campo de texto para que los usuarios puedan descartar el campo de texto. Todo esto debería ser una revisión del capítulo anterior. Primero, agreguemos algunas propiedades al archivo de encabezado:

1
// EditViewController.h

2
#import <UIKit/UIKit.h>
3
4
@interface EditViewController : UITableViewController
5
6
@property (strong, nonatomic) id detailItem;
7
8
@property (weak, nonatomic) IBOutlet UITextField *firstNameField;
9
@property (weak, nonatomic) IBOutlet UITextField *lastNameField;
10
@property (weak, nonatomic) IBOutlet UITextField *phoneNumberField;
11
@property (weak, nonatomic) IBOutlet UITextField *organizationField;
12
13
@end

La implementación se parece mucho a DetailViewController.m. Todo lo que hace es asegurarse de que los campos de texto se actualicen cuando se cambia la propiedad detailItem:

1
// EditViewController.m

2
#import "EditViewController.h"
3
#import "Person.h"
4
5
@implementation EditViewController
6
7
@synthesize detailItem = _detailItem;
8
@synthesize firstNameField = _firstNameField;
9
@synthesize lastNameField = _lastNameField;
10
@synthesize phoneNumberField = _phoneNumberField;
11
@synthesize organizationField = _organizationField;
12
13
- (void)setDetailItem:(id)detailItem {
14
    if (_detailItem != detailItem) {
15
        _detailItem = detailItem;
16
        [self configureView];
17
    }
18
}
19
20
- (void)configureView {
21
    if (self.detailItem && [self.detailItem isKindOfClass:[Person class]]) {
22
        self.firstNameField.text = [self.detailItem firstName];
23
        self.lastNameField.text = [self.detailItem lastName];
24
        self.phoneNumberField.text = [self.detailItem phoneNumber];
25
        self.organizationField.text = [self.detailItem organization];
26
    }
27
}
28
29
- (void)viewDidLoad {
30
    [super viewDidLoad];
31
    [self configureView];
32
}
33
34
- (void)didReceiveMemoryWarning {
35
    [super didReceiveMemoryWarning];
36
}
37
38
@end

A continuación, necesitamos preparar el campo de texto delegado. En EditViewController.h, díle a la clase que adopte el protocolo UITextFieldDelegate con la siguiente línea:

1
@interface EditViewController : UITableViewController <UITextFieldDelegate>
2
As in the previous chapter, we can dismiss the keyboard by implementing the textFieldShouldReturn: method. Add the following to EditViewController.m:
3
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
4
    if ((textField == self.firstNameField) ||
5
        (textField == self.lastNameField) ||
6
        (textField == self.phoneNumberField) ||
7
        (textField == self.organizationField)) {
8
        [textField resignFirstResponder];
9
    }
10
    return YES;
11
}

Recuerda que se llama al método prepareForSegue:sender: en la escena de origen justo antes de que iOS cambie a la escena de destino. Al igual que hicimos en la escena maestra, usaremos esto para enviar el elemento seleccionado a la escena de edición. En DetailViewController.m, agrega el siguiente método:

1
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
2
    if ([[segue identifier] isEqualToString:@"editDetail"]) {
3
        NSArray *navigationControllers = [[segue destinationViewController] viewControllers];
4
        EditViewController *editViewController = [navigationControllers objectAtIndex:0];
5
        [editViewController setDetailItem:self.detailItem];
6
    }
7
}

Recuerda que la escena de edición está incrustada en un controlador de navegación, por lo que la segue modal apunta al controlador de navegación, no a la escena de edición en sí. Este controlador de navegación intermedio agrega un paso adicional del que no tuvimos que preocuparnos en el método prepareForSegue:sender: de la escena maestra. Para obtener la escena de edición, necesitamos consultar la propiedad viewControllers del controlador de navegación, que es una matriz que contiene su pila de navegación. Dado que la escena de edición es el único controlador de vista secundario, podemos acceder a ella a través de la llamada objectAtIndex:0. Una vez que tenemos la instancia de EditViewController, simplemente reenviamos el elemento seleccionado de la escena de detalle a la escena de edición.

Conexiones de salida y delegado

De vuelta en el guión gráfico, conectemos los medios y los delegados que acabamos de exponer. Para los puntos de venta, selecciona el icono amarillo en el dock de la escena de edición, abre el inspector de conexiones y arrastra desde los círculos firstNameField, lastNameField, organizationField y phoneNumberField a los campos de texto correspondientes en la escena.

tutorial_imagetutorial_imagetutorial_imageFigura 73: Creando las conexiones de salida

Para configurar EditViewController como delegado para los campos de texto, selecciona cada campo de texto, abre el inspector de conexiones y arrastra desde el círculo de delegado al icono amarillo en el dock, como se muestra en la siguiente captura de pantalla. Has esto para cada campo de texto.

tutorial_imagetutorial_imagetutorial_imageFigura 74: Creando las conexiones delegadas

Cuando compiles el proyecto, deberías poder iniciar la escena de edición y ver los campos de texto rellenados con las propiedades del objeto Persona seleccionado. Con suerte, a estas alturas, te sentirás relativamente cómodo haciendo este tipo de conexiones de salida y delegado por tu cuenta.

Puedes editar los valores, pero como aún no hemos implementado los botones Cancelar o Guardar, no podrás alterar el objeto Persona subyacente o incluso navegar fuera de la escena de edición.

Desenrolla Segues

¿Recuerdas ese botón maestro que apareció automáticamente en la barra de navegación de la escena detallada? El controlador de navegación para las escenas maestra/detallada configuró este botón "atrás" para nosotros, pero como estamos usando un segue modal, debemos descartar manualmente la escena de edición presentada de manera modal. Usaremos lo que se llama una transición de relajación para volver a la escena de los detalles.

La principal diferencia entre un segue de desenrollado y otros segues es que el primero utiliza una escena existente como destino, mientras que los segues modales y push crean una nueva instancia de tu escena de destino. Es importante tener esto en cuenta si estás haciendo muchas transiciones de un lado a otro.

El proceso de desenrollar una escena también es un poco diferente a iniciar una transición de empuje. Utiliza el patrón de diseño objetivo-acción, que discutimos en el capítulo anterior. Además de llamar al método prepareForSegue:sender: en la escena de origen, un segue de desenrollado llama a un método arbitrario en la escena de destino (DetailViewController). Sigamos adelante y declaremos una acción de cancelación y guardado en DetailViewController.h:

1
- (IBAction)save:(UIStoryboardSegue *)sender;
2
- (IBAction)cancel:(UIStoryboardSegue *)sender;

En un momento, vamos a adjuntar estos métodos a los botones Cancelar y Guardar en la escena de edición. Pero primero, debemos implementarlos. Agrega los siguientes métodos a DetailViewController.m:

1
- (IBAction)save:(UIStoryboardSegue *)segue {
2
    if ([[segue identifier] isEqualToString:@"saveInput"]) {
3
        EditViewController *editController = [segue sourceViewController];
4
        [self.detailItem setFirstName:editController.firstNameField.text];
5
        [self.detailItem setLastName:editController.lastNameField.text];
6
        [self.detailItem setPhoneNumber:editController.phoneNumberField.text];
7
        [self.detailItem setOrganization:editController.organizationField.text];
8
        [self configureView];
9
    }
10
}
11
12
- (IBAction)cancel:(UIStoryboardSegue *)segue {
13
    if ([[segue identifier] isEqualToString:@"cancelInput"]) {
14
        // Custom cancel handling can go here.

15
    }
16
}

Estos son bastante sencillos. El método guardar: actualiza las propiedades de detailItem según los valores del campo de texto de la escena de edición y luego actualiza sus etiquetas llamando a configureView. El método cancelar: simplemente ignora todo lo que sucedió en la escena de edición. Ahora, podemos crear una secuencia de desenrollado para descartar la escena de edición y llamar al método apropiado. La configuración de las secuencias de desenrollado es similar a la creación de segues: tu controlas y arrastras desde el componente de la interfaz de usuario que inicia la transición al icono verde de salida en el dock. Este icono está dedicado exclusivamente a crear secuencias de relajación.

tutorial_imagetutorial_imagetutorial_imageFigura 75: El icono de salida en el muelle (extremo derecho)

Por lo tanto, mantén presionada la tecla Control y arrastra desde el botón Guardar en la escena de edición hasta el icono Salir en el dock, como se muestra en la siguiente figura:

tutorial_imageFigura 76: Creación de la secuencia de desenrollado para el botón Guardar

Aparecerá un menú que te pedirá que asocies una acción con el segue:

tutorial_imageFigura 77: Selección de la acción para la secuencia de relajación

Por supuesto, querrás elegir guardar:. Eso es todo lo que necesitas hacer para crear la transición de relajación. Después de repetir el proceso para el botón Cancelar, deberías ver ambas secuencias de desenrollado en el esquema del documento:

tutorial_imageFigura 78: Los pasos de desenrollado en el esquema del documento

A diferencia de los segues push y modales, los segues de desenrollado no tienen representación visual en el generador de interfaz, por lo que el esquema del documento es la única forma de seleccionarlos. Nuestro último paso será agregar identificadores únicos a ambos segmentos a través del inspector de atributos. Usa cancelInput para el botón Cancelar y saveInput para el botón Guardar (ten en cuenta que estos son los identificadores que verificamos en los métodos cancelar: y guardar:, respectivamente). Nuevamente, dado que nuestra aplicación de ejemplo es tan simple, agregar identificadores de segue es más un paso de mejores prácticas que una necesidad.

tutorial_imageFigura 79: Definición de los identificadores de segue de desenrollado

Puedes pensar en una transición de relajación como una combinación de una transición y un botón. El segue se encarga de descartar la escena (es decir, la transición a la escena principal), pero dado que se inicia presionando un botón, también puedes adjuntarle un método utilizando el patrón de acción objetivo.

Nuestra escena de edición ahora está completa y deberías poder compilar el proyecto, ingresar valores en los campos de texto de la escena de edición y elegir cancelar o guardar tus cambios. Dado que el método guardar: llama a configureView después de guardar los nuevos valores, la escena de detalles se actualizará para reflejar las ediciones. Sin embargo, nunca le dijimos a la escena maestra que se actualizara, por lo que tus cambios no se reflejarán en la lista maestra.

Actualización de la lista maestra

Lo último que tenemos que repasar en este capítulo es actualizar la tabla de la escena maestra para reflejar cualquier cambio en los datos subyacentes. Hay varias formas de hacer esto, pero la más fácil (aunque no necesariamente la más eficiente) es recargar la tabla cada vez que se muestra la escena maestra.

UIViewController define un método llamado viewWillAppear: y lo llama justo antes de que se muestre la escena asociada. Esto es diferente a viewDidLoad:, que obtienes la primera vez que se muestra la vista. Dado que el controlador de navegación principal muestra la misma instancia de la escena maestra cada vez que el usuario navega hacia ella, necesitamos usar el método viewWillAppear: en lugar de viewDidAppear:. En MasterViewController.m, agrega el siguiente método:

1
- (void)viewWillAppear:(BOOL)animated {
2
    [super viewWillAppear:animated];
3
    UITableView *view = (UITableView *)self.view;
4
    [view reloadData];
5
}

Primero, pasamos el método a super y luego obtenemos la instancia raíz de UIView del controlador a través de la propiedad view. Podemos suponer que esto es un UITableView porque MasterViewController hereda de UITableViewController, pero aún necesitamos convertirlo para evitar que el compilador se queje. El método reloadData de UITableView regenera las celdas de la tabla en función del conjunto de datos subyacente (la matriz _objects), y la lista maestra ahora debería reflejar los cambios que guardaste de la escena de edición.

tutorial_imagetutorial_imagetutorial_imageFigura 80: La escena maestra completa

Resumen

En este capítulo, aprendimos cómo administrar múltiples escenas dentro de una sola aplicación. Experimentamos con UITableViewControllers, UINavigationControllers y todo tipo de segues. Uno de los conceptos más importantes para extraer de este capítulo es cómo transferimos los datos entre cada escena: a través del método prepareForSegue:sender: y los métodos guardar: y cancelar: para el proceso de desenrollado. La mayoría de las aplicaciones son en realidad editores fáciles de usar para estructuras de datos complejas, por lo que comprender cómo se transmiten los datos ayuda en gran medida a organizar proyectos de iOS de manera eficiente.

Los dos capítulos anteriores cubrieron todo lo que necesitas saber para crear interfaces de usuario simples. En el resto de esta serie, exploraremos otros marcos de trabajo de iOS para acceder a activos multimedia, localizar recursos y reproducir efectos de sonido de la interfaz de usuario.

Esta lección representa un capítulo sucinto de iOS, un libro electrónico gratuito del equipo de Syncfusion.