Saltar al contenido

Pasar datos entre controladores de vista

Bienvenido a nuestro sitio, en este sitio encontrarás la resolución que necesitas.

Solución:

Esta pregunta parece ser muy popular aquí en Stack Overflow, así que pensé en intentar dar una mejor respuesta para ayudar a las personas que comienzan en el mundo de iOS como yo.

Espero que esta respuesta sea lo suficientemente clara para que la gente la entienda y que no me haya perdido nada.

Pasar datos hacia adelante

Pasar datos a un controlador de vista desde otro controlador de vista. Usaría este método si quisiera pasar un objeto / valor de un controlador de vista a otro controlador de vista que puede estar empujando a una pila de navegación.

Para este ejemplo, tendremos ViewControllerA y ViewControllerB

Para pasar un BOOL valor de ViewControllerA para ViewControllerB haríamos lo siguiente.

  1. en ViewControllerB.h crear una propiedad para el BOOL

     @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. en ViewControllerA tienes que contarlo sobre ViewControllerB así que usa un

     #import "ViewControllerB.h"
    

Luego, dónde desea cargar la vista, por ejemplo, didSelectRowAtIndex o algunos IBAction, debe establecer la propiedad en ViewControllerB antes de colocarlo en la pila de navegación.

    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.isSomethingEnabled = YES;
    [self pushViewController:viewControllerB animated:YES];

Esto establecerá isSomethingEnabled en ViewControllerB para BOOL valor YES.

Pasar datos hacia adelante usando Segues

Si está utilizando Storyboards, lo más probable es que esté utilizando segues y necesitará este procedimiento para transmitir los datos. Esto es similar a lo anterior, pero en lugar de pasar los datos antes de presionar el controlador de vista, usa un método llamado

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

Entonces para pasar un BOOL de ViewControllerA para ViewControllerB haríamos lo siguiente:

  1. en ViewControllerB.h crear una propiedad para el BOOL

     @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. en ViewControllerA tienes que contarlo sobre ViewControllerB, así que usa un

     #import "ViewControllerB.h"
    
  3. Crea la transición desde ViewControllerA para ViewControllerB en el guión gráfico y asígnele un identificador. En este ejemplo lo llamaremos "showDetailSegue"

  4. A continuación, debemos agregar el método a ViewControllerA que se llama cuando se realiza cualquier segue. Debido a esto, necesitamos detectar qué segue se llamó y luego hacer algo. En nuestro ejemplo, buscaremos "showDetailSegue" y si se realiza, pasaremos nuestro BOOL valor para ViewControllerB

     -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
         if([segue.identifier isEqualToString:@"showDetailSegue"])
             ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
             controller.isSomethingEnabled = YES;
         
     
    

Si tiene sus vistas incrustadas en un controlador de navegación, debe cambiar ligeramente el método anterior a lo siguiente

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
        if([segue.identifier isEqualToString:@"showDetailSegue"])
            UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
            ViewControllerB *controller = (ViewControllerB *)navController.topViewController;
            controller.isSomethingEnabled = YES;
        
    

Esto establecerá isSomethingEnabled en ViewControllerB para BOOL valor YES.

Pasando datos de vuelta

Para devolver datos de ViewControllerB para ViewControllerA necesitas usar Protocolos y delegados o Bloques, este último se puede utilizar como un mecanismo débilmente acoplado para devoluciones de llamada.

Para hacer esto haremos ViewControllerA un delegado de ViewControllerB. Esto permite ViewControllerB para enviar un mensaje a ViewControllerA permitiéndonos enviar datos de vuelta.

Para ViewControllerA ser delegado de ViewControllerB debe ajustarse a ViewControllerBes el protocolo que tenemos que especificar. Esto dice ViewControllerA qué métodos debe implementar.

  1. En ViewControllerB.h, bajo el #import, pero arriba @interface usted especifica el protocolo.

     @class ViewControllerB;
    
     @protocol ViewControllerBDelegate 
     - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
     @end
    
  2. Siguiente todavía en el ViewControllerB.h, necesitas configurar un delegate propiedad y sintetizar en ViewControllerB.m

     @property (nonatomic, weak) id  delegate;
    
  3. En ViewControllerB llamamos un mensaje en el delegate cuando abrimos el controlador de vista.

     NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
     [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
    
  4. Eso es todo por ViewControllerB. Ahora en ViewControllerA.h, contar ViewControllerA importar ViewControllerB y cumplir con su protocolo.

     #import "ViewControllerB.h"
    
     @interface ViewControllerA : UIViewController 
    
  5. En ViewControllerA.m implementar el siguiente método de nuestro protocolo

     - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
     
         NSLog(@"This was returned from ViewControllerB %@", item);
     
    
  6. Antes de empujar viewControllerB a la pila de navegación tenemos que decirle ViewControllerB ese ViewControllerA es su delegado, de lo contrario obtendremos un error.

     ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
     viewControllerB.delegate = self
     [[self navigationController] pushViewController:viewControllerB animated:YES];
    

Referencias

  1. Uso de la delegación para comunicarse con otros controladores de vista en el Ver la guía de programación del controlador
  2. Patrón de delegado

Centro de notificaciones NS

Es otra forma de transmitir datos.

// Add an observer in controller(s) where you want to receive data
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"handleDeepLinking" object:nil];

-(void) handleDeepLinking:(NSNotification *) notification 
    id someObject = notification.object // Some custom object that was passed with notification fire.


// Post notification
id someObject;
[NSNotificationCenter.defaultCenter postNotificationName:@"handleDeepLinking" object:someObject];

Pasar datos de una clase a otra (Una clase puede ser cualquier controlador, administrador de sesión / red, subclase UIView o cualquier otra clase)

Los bloques son funciones anónimas.

Este ejemplo pasa datos de Controlador B para Controlador A

Definir un bloque

@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h

Agregar controlador de bloque (oyente)

Donde necesita un valor (por ejemplo, necesita su respuesta API en ControllerA o necesita datos de ContorllerB en A)

// In ContollerA.m

- (void)viewDidLoad 
    [super viewDidLoad];
    __unsafe_unretained typeof(self) weakSelf = self;
    self.selectedVoucherBlock = ^(NSString *voucher) 
        weakSelf->someLabel.text = voucher;
    ;

Ir al controlador B

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];
vc.sourceVC = self;
    [self.navigationController pushViewController:vc animated:NO];

Bloque de fuego

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath 
    NSString *voucher = vouchersArray[indexPath.row];
    if (sourceVC.selectVoucherBlock) 
        sourceVC.selectVoucherBlock(voucher);
    
    [self.navigationController popToViewController:sourceVC animated:YES];

Otro ejemplo práctico para bloques

Rápido

Hay toneladas y toneladas de explicaciones aquí y en torno a Stack Overflow, pero si eres un principiante y solo estás tratando de hacer que algo básico funcione, intenta ver este tutorial de YouTube (es lo que me ayudó a entender finalmente cómo hacerlo).

  • Tutorial de YouTube: Cómo enviar datos a través de segue (Swift)

Pasar datos al siguiente controlador de vista

El siguiente es un ejemplo basado en el video. La idea es pasar un string desde el campo de texto en el controlador de primera vista a la etiqueta en el controlador de segunda vista.

Ingrese la descripción de la imagen aquí

Cree el diseño del guión gráfico en Interface Builder. Para hacer la transición, solo Control haga clic en el botón y arrastre hasta el controlador de segunda vista.

Controlador de primera vista

El código para el controlador de primera vista es

import UIKit

class FirstViewController: UIViewController 

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

        // Get a reference to the second view controller
        let secondViewController = segue.destination as! SecondViewController

        // Set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    


Controlador de segunda vista

Y el código para el controlador de segunda vista es

import UIKit

class SecondViewController: UIViewController 

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() 
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    


No olvides

  • Conecte los enchufes para el UITextField y el UILabel.
  • Configure el primer y segundo controlador de vista en los archivos Swift apropiados en Interface Builder.

Pasar datos al controlador de vista anterior

Para devolver datos del segundo controlador de vista al primer controlador de vista, usa un protocolo y un delegado. Este video es un recorrido muy claro de ese proceso:

  • Tutorial de YouTube: Tutorial básico de iOS Swift: Protocolos y delegados Pero también lea esta publicación para asegurarse de no entrar en un ciclo de referencia sólido.

El siguiente es un ejemplo basado en el video (con algunas modificaciones).

Ingrese la descripción de la imagen aquí

Cree el diseño del guión gráfico en Interface Builder. De nuevo, para hacer la transición, solo Control arrastre desde el botón hasta el controlador de segunda vista. Establezca el identificador de segue en showSecondViewController. Además, no olvide conectar los puntos de venta y las acciones usando los nombres en el siguiente código.

Controlador de primera vista

El código para el controlador de primera vista es

import UIKit

class FirstViewController: UIViewController, DataEnteredDelegate 

    @IBOutlet weak var label: UILabel!

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if segue.identifier == "showSecondViewController" 
            let secondViewController = segue.destination as! SecondViewController
            secondViewController.delegate = self
        
    

    func userDidEnterInformation(info: String) 
        label.text = info
    

Tenga en cuenta el uso de nuestra costumbre DataEnteredDelegate protocolo.

Controlador y protocolo de segunda vista

El código para el segundo controlador de vista es

import UIKit

// Protocol used for sending data back
protocol DataEnteredDelegate: AnyObject 
    func userDidEnterInformation(info: String)


class SecondViewController: UIViewController 

    // Making this a weak variable, so that it won't create a strong reference cycle
    weak var delegate: DataEnteredDelegate? = nil

    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) 

        // Call this method on whichever class implements our delegate protocol
        delegate?.userDidEnterInformation(info: textField.text!)

        // Go back to the previous view controller
        _ = self.navigationController?.popViewController(animated: true)
    

Tenga en cuenta que el protocol está fuera de la clase View Controller.

Eso es todo. Al ejecutar la aplicación ahora, debería poder enviar datos desde el segundo controlador de vista al primero.

La M en MVC es para “Modelo” y en el paradigma MVC la función de las clases modelo es administrar los datos de un programa. Un modelo es lo opuesto a una vista: una vista sabe cómo mostrar datos, pero no sabe nada sobre qué hacer con los datos, mientras que un modelo sabe todo sobre cómo trabajar con datos, pero nada sobre cómo mostrarlos. Los modelos pueden ser complicados, pero no es necesario que lo sean; el modelo de su aplicación puede ser tan simple como un array de cadenas o diccionarios.

El papel de un controlador es mediar entre la vista y el modelo. Por lo tanto, necesitan una referencia a uno o más objetos de vista y uno o más objetos de modelo. Digamos que tu modelo es un array de diccionarios, y cada diccionario representa una fila en su tabla. La vista raíz de su aplicación muestra esa tabla, y podría ser responsable de cargar el array desde un archivo. Cuando el usuario decide agregar una nueva fila a la tabla, toca algún botón y su controlador crea un nuevo diccionario (mutable) y lo agrega al array. Para completar la fila, el controlador crea un controlador de vista detallada y le da el nuevo diccionario. El controlador de vista de detalles completa el diccionario y regresa. El diccionario ya es parte del modelo, por lo que no es necesario que suceda nada más.

Comentarios y calificaciones del artículo

Eres capaz de estimular nuestra publicación exponiendo un comentario y dejando una valoración te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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