ios - perform - swift segue programmatically
Pasar datos entre los Controladores de Vista usando Segue (6)
Use el patrón Singleton:
El patrón de Singleton en ingeniería de software es un patrón de diseño que garantiza que una clase tenga solo una instancia y proporcione un punto de acceso global a ella.
Como tiene una instancia única, las variables de clase y los métodos se comparten en toda la aplicación / espacio de nombres.
Ejemplo:
class Singleton {
static let sharedInstance = Singleton()
var studentId = 1281
}
Y puede usarlo en cualquier lugar de su aplicación de esta manera:
var studentId = Singleton.sharedInstance.studentId
print("Student Id: /(studentId)")
Soy nuevo en iOS. Estoy enfrentando un problema al pasar los datos entre ViewControllers. Tengo tres viewControllers (view_1, view_2 y view_3).
Aquí mi configuración: -
- Selecciona view_1
- empuja view_2
- empuja view_3
Deseo enviar la referencia de ViewController (id) de ''view_1'' a ''view_3''. entonces include "view_3"
en "view_1" y establece el valor en la variable de "view_3" (usando view_3 *v3=[[view_3 alloc] init ]; v3.reference=self;
). En la consola, muestra:
Controlador de vista: -; <ViewController: 0x89e9540>
en ''view_1'' pero en ''view_3'', en la consola se muestra
ver el controlador (nulo)
Pero cuando utilicé ''view_2'' para pasar estos datos su trabajo. ¿Pero cómo? Quiero saber este comportamiento, ¿y hay alguna solución para crear esto?
por favor ayuda.
"Pasar datos al controlador de destino" cuando se desencadena un segue se logrará reemplazando el método prepareForSegue:sender:
Generalmente, pasa los datos y NO el controlador de vista de origen al controlador de vista de destino. "datos" puede ser un cierto aspecto de su "modelo" de aplicación. Es un objeto como "Usuario", o tal vez una matriz que contiene "Usuario", etc.
El controlador de vista de destino no debe tener ningún conocimiento del controlador de vista de origen . Eso significa que el controlador de vista de destino no necesita importar el encabezado del controlador de vista de origen.
Por otro lado, el controlador de vista de origen puede tener conocimiento de la clase concreta del controlador de vista de destino o una clase base del controlador de vista de destino, y por lo tanto importará el encabezado del controlador de vista de destino.
Ver: Configurar el controlador de destino cuando se activa un Segue
Si necesita algún tipo de "protocolo de comunicación" entre el origen y el destino, puede emplear Delegación para comunicarse con otros controladores de vista. Esto implica la definición de un @protocol (por ejemplo, tener un método doneButton
) y un delegate
propiedad que se define en el controlador de vista de destino. El protocolo debe definirse en el encabezado del controlador de vista de destino, si es específico del controlador de vista de destino. Normalmente, usted define el protocolo desde el punto de vista del controlador de destino y no desde los requisitos del controlador de origen.
El controlador de vista de origen crea un delegado (a menos que ya lo esté) y establece el delegate
del controlador de vista de destino. El controlador de vista de destino enviará los métodos de delegado al delegado y el delegado lo manejará.
Ahora, pasar "datos" de un VC_A a VC_B debe ser sencillo. Debería leer algunos ejemplos que usan prepareForSegue:sender:
Por ejemplo, el controlador de vista de destino puede tener data
propiedad que representan lo que debería mostrar. El controlador de vista de origen debe establecer esta propiedad en prepareForSegue:sender:
Pasar datos de VC_A sobre VC_B a VC_C también debería ser sencillo.
Nota: Cada controlador de vista puede adaptar (separar, modificar, preparar, cortar, transformar, etc.) sus data
para convertirlos en data
adecuados para el próximo controlador de vista.
Si VC_C necesita datos que no están disponibles en su controlador de vista fuente VC_B, entonces hay un par de enfoques para resolver esto. Sin embargo, esto suele ser un signo de mal diseño .
Podría tener un modelo de aplicación, que es global . Supongamos que su "modelo de aplicación" es un objeto de tipo Document
. Supongamos que, en cualquier momento, solo hay una instancia de ese modelo de aplicación. Luego, el modelo es un "Singleton", al cual se puede acceder desde cualquier lugar de su aplicación, de esta manera:
Document* document = [Document sharedDocument];
Sin embargo, la forma preferida de obtener una instancia de un modelo es en el controlador de primera vista que requiere acceso a él, en este caso: VC_A.
Entonces, VC_A pasa una instancia de Document
al siguiente controlador de vista VC_B. Y VC_B pasa el objeto del documento a VC_C.
Debe leer la documentación oficial " Ver la guía de programación del controlador para iOS ".
Ejemplo 1
Supongamos que tiene una lista de "Usuarios". La lista debe mostrarse en un controlador de vista de tabla, y también debe haber una vista de detalle, que muestra detalles de un Usuario.
El controlador de vista de tabla tendrá una propiedad de "datos" para los users
:
En UsersTableViewController.h :
@interface UsersTableViewController : UIViewController
@property (nonatomic, readonly) NSArray* users;
@end
(Estrictamente, esta propiedad del user
no necesita ser pública. Por ejemplo, si la vista de tabla obtiene internamente la lista de usuarios, no es necesario acceder desde el exterior.
La matriz de "usuarios" es la información de la vista de tabla que se mostrará en filas. Cada fila muestra un "resumen" de un usuario.
Se deben mostrar más detalles de un usuario en un controlador de vista detallada . Los datos del controlador de vista detallada son un único usuario de tipo User
.
Cuando el usuario marca una determinada fila en la vista de tabla, se mostrará el controlador de vista detallada. Antes de que se muestre, el controlador de vista de tabla debe configurar el controlador de vista de detalle: el controlador de vista de tabla asigna la "propiedad de datos" del controlador de vista de detalle al usuario seleccionado actual. Por lo tanto, el controlador de vista detallada debe tener un user
propiedad pública :
@interface UserViewController : UIViewController
@property (nonatomic) User* user;
@end
El controlador de vista de tabla configura el controlador de vista detallada en prepareForSegue:sender:
:
En UsersTableViewController.m
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"ShowUserDetails"]) {
UserViewController* userViewController = [segue destinationViewController];
userViewController.user = [self.users objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
Ejemplo 2
El segundo ejemplo es más complejo y usa "Delegación" como medio para establecer una comunicación entre los controladores.
Precaución:
Este no es un ejemplo completo. El propósito de este ejemplo demostrará cómo usar "Delegación". Una implementación completa de las tareas de datos como se muestra en el ejemplo requerirá un esfuerzo mucho mayor. En estos escenarios como estos, "Delegación" será el enfoque más preferido para lograr esto (en mi humilde opinión).
Supongamos que queremos
- Mostrar un usuario
- Modificar (editar) un usuario
- Crear un nuevo usuario, y
- Eliminar un usuario
desde dentro de la vista de detalle.
Estas "tareas de datos" no deben ser realizadas por el propio controlador de vista detallada, sino que un delegado es responsable de estas tareas de datos.
Estas acciones de datos serán manejadas por el delegado:
@protocol UserDataSourceDelegateProtocol <NSObject>
- (User*) viewControllerUser:(UserViewControllerBase*)viewController;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithUpdatedUser:(User*)user;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithDeletedUser:(User*)user;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithCreatedUser:(User*)user;
@end
Este protocolo refleja los métodos CRUD básicos (Crear, Leer, Actualizar, Eliminar).
Nuevamente, no deseamos que el Controlador de Vista de Detalle realice estos métodos de datos, sino que una instancia que implemente el UserDataSourceDelegateProtocol
. El controlador de vista detallada tiene una propiedad de este delegado y envía estas "tareas de datos" al delegado.
Puede haber varios controladores de visualización de detalles, todas las subclases de la clase abstracta UserViewControllerBase
que manejan el espectáculo , editan y crean tareas. La eliminación de un usuario se puede realizar en la vista de tabla y en el controlador de vista "Mostrar usuario":
-
ShowUserViewController
-
EditUserViewController
-
NewUserViewController
Por ejemplo, EditUserViewController
enviará viewController:dismissWithUpdatedUser:
cuando el usuario presiona el botón "Atrás" Y si el usuario ha modificado el objeto del usuario. Ahora, el delegado puede o no permitir descartar la vista detallada. Puede no permitirlo cuando hay errores de validación, por ejemplo.
El protocolo UserDataSourceDelegateProtocol
se puede implementar en el controlador de vista raíz, el controlador de vista de tabla, por ejemplo. Sin embargo, una clase separada cuya única responsabilidad es manejar tareas de datos puede ser más apropiada. En el ejemplo siguiente, el controlador de vista de tabla también será este manejador de datos.
El UserDataSourceDelegateProtocol
se puede definir en un encabezado adicional.
En UsersTableViewController.m :
#import "UserDataSourceDelegateProtocol.h"
#import "ShowUserViewController.h"
@interface UsersTableViewController () <UserDataSourceDelegateProtocol>
@property (nonatomic, readonly) NSArray* users;
@end
// This delegate will be called when the detail view controller request
// the user object which shall be displayed.
- (User*) viewControllerUser:(UserViewControllerBase*)viewController {
return [self.users objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
}
Aquí, el Controlador de vista de tabla configura el Controlador de vista de detalles de usuario de la vista:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:UserShowSegueID])
{
ShowUserViewController* showViewController = segue.destinationViewController;
showViewController.delegate = self; // Data Source Handler is self
}
}
El controlador de vista "Editar usuario" suele ser un controlador de vista de destino del controlador de vista "Mostrar usuario", que se visualiza cuando el usuario presiona el botón "Editar".
El controlador de vista "Mostrar usuario" configurará al delegado para que el controlador de vista "Editar usuario" obtenga el mismo delegado:
En ShowUserViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:UserEditSegueID])
{
EditUserViewController* editViewController = segue.destinationViewController;
editViewController.delegate = self.delegate; // pass through the data source hanlder
}
}
El delegado de datos puede manejar un usuario actualizado de la siguiente manera:
En UsersTableViewController.m :
- (void) viewController:(UserViewControllerBase*)viewController
dismissWithUpdatedUser:(User*)user {
if (/* is valid user and can be saved */) {
[viewController.presentingViewController dismissViewControllerAnimated:YES
completion:nil];
}
}
Mejor y fácil solución.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"webView"];
webView = (WebViewController *)vc;
webView.strWebLink = @"http://www.Google.com/";
[self.navigationController showViewController:vc sender:self];
en Swift 4.0
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! SecondViewController
vc.username = self.username
}
Asegurarse
segue.destination
es la verdadera diferencia aquí.
ya hay una solución pero no de la manera más adecuada.
ViewController3.h
-(void)getUser:(NSString *)strPassedUser;
vaya a su ViewController3.m y sobre la interfaz @ agregue una variable como esta
NSString *recievingVariable ;
luego algunos dentro de ViewController3.m
-(void)getUser:(NSString *)strPassedUser
{
recievingVariable = strPassedUser;
}
ViewController1 e importar ViewController3 luego haga esto ...
ViewController3 * vc3 = [ViewController3 alloc]getUser :@"me"];
en este caso, se getUser
su función getUser
obtendrá getUser
receivingVariable= me
.
Este proyecto de Swift en YouTube me ayudó finalmente a entender cómo hacer esto.
Configuré un ejemplo simple a lo largo de líneas similares. Escriba un texto en un campo de texto, presione el botón y coloca el texto en una etiqueta en el siguiente controlador de vista.
Configura el guión gráfico
No es muy difícil. Cree el diseño del guión gráfico en Interface Builder. Para hacer la transición que acaba de controlar, haga clic en el botón y arrastre hacia el Controlador de segunda vista.
Primer controlador de vista
El código para el First View Controller es
import UIKit
class FirstViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
// This function is called before the segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// get a reference to the second view controller
let secondViewController = segue.destinationViewController 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 segundo controlador de 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 lo olvides
-
UITextField
las tomas deUITextField
yUILabel
. - Establezca el primer y segundo controlador de vista en los archivos Swift apropiados en IB.
El proceso para pasar los datos a un controlador de tercera vista sería el mismo.