iphone - que - Pasa los datos al control de vista anterior
viewcontroller swift (7)
Estoy tratando de pasar los datos VOLVER A viewController anterior.
¿Alguien sabe cómo pasar datos de ViewController B a ViewController A? Así que quiero que una cadena vaya ''de'' BIDAddTypeOfDealViewController a BIDDCCreateViewController. Un usuario edita viewController B y quiero que los datos editados vuelvan a ViewController A, donde luego los uso.
Estoy usando la sección ''pasar datos atrás'' de esta respuesta . Cómo difiere el mío: los puntos 3 y 6 solo mencionan cuando se muestran las vistas, así que puse ese código en viewWillDisappear. Creo que eso es correcto? También en el punto 6 no inicié con la punta ya que es antiguo. Estoy usando guiones gráficos. Y no agregué esa última línea ya que no creo que tenga que presionarla. Presionar un botón en mi guión gráfico ya me lleva hacia adelante.
Creo que el problema puede surgir en BIDDCCreateViewController, tengo el método pero no puedo ejecutarlo. Para ejecutar un método, debe ir [self method]. No puedo hacer eso. Bueno, eso es exactamente lo que estoy adivinando.
Se compila y funciona bien simplemente no se registra nada, por lo que no sé si funciona.
ACTUALIZACIÓN: no puedo ejecutar el método ''sendDataToA''.
#import <UIKit/UIKit.h>
#import "BIDAddTypeOfDealViewController.h"
@interface BIDDCCreateViewController : UIViewController
@property (strong, nonatomic) NSString *placeId;
- (IBAction)gotoBViewController:(id)sender;
@end
#import "BIDDCCreateViewController.h"
#import "BIDAddTypeOfDealViewController.h"
@implementation BIDDCCreateViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"SUCCESSFULLY PASSED PLACE ID: %@", self.placeId);
}
-(void)sendDataToA:(NSString *)myStringData
{
NSLog(@"Inside sendDataToA");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Your string Data Showing" message:myStringData delegate:self cancelButtonTitle:@"Ok " otherButtonTitles:nil];
[alert show];
}
- (IBAction)gotoBViewController:(id)sender {
NSLog(@"pressed");
BIDAddTypeOfDealViewController *bidAddType = [[BIDAddTypeOfDealViewController alloc]init];
bidAddType.delegate = self;
}
@end
@protocol senddataProtocol <NSObject>
-(void)sendDataToA:(NSString *)myStringData;
@end
#import <UIKit/UIKit.h>
@interface BIDAddTypeOfDealViewController : UIViewController <UITextFieldDelegate>//Using this delegate for data a user inputs
@property(nonatomic,assign)id delegate;
//other textfield outlets not relevant
- (IBAction)chooseDiscountDeal:(id)sender;
@end
#import "BIDAddTypeOfDealViewController.h"
@interface BIDAddTypeOfDealViewController ()
@end
@implementation BIDAddTypeOfDealViewController
@synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillDisappear:(BOOL)animated
{
[delegate sendDataToA:@"Apple"];
}
@end
Swift: envío de datos utilizando el patrón delegado
Mi respuesta completa que cubre el paso de datos en ambos sentidos está here . Mi respuesta que explica el patrón del delegado está here .
Para pasar datos desde el segundo controlador de vista al primer controlador de vista, usa un protocolo y un delegado. Este video es una caminata muy clara 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 fuerte.
El siguiente es un ejemplo basado en el video (con algunas modificaciones).
Cree el diseño del guión gráfico en Interface Builder. Nuevamente, para hacer la transición, simplemente controle arrastrar desde el botón hasta el controlador de segunda vista. Establezca el identificador de segue para showSecondViewController
. Además, no se olvide de conectar los puntos de venta y las acciones usando los nombres en el siguiente código.
Primer controlador de vista
El código para el First View Controller es
import UIKit
class FirstViewController: UIViewController, DataEnteredDelegate {
@IBOutlet weak var label: UILabel!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destinationViewController as! SecondViewController
secondViewController.delegate = self
}
}
func userDidEnterInformation(info: String) {
label.text = info
}
}
Tenga en cuenta el uso de nuestro protocolo DataEnteredDelegate
personalizado.
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: class {
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: UIButton) {
// call this method on whichever class implements our delegate protocol
delegate?.userDidEnterInformation(textField.text!)
// go back to the previous view controller
self.navigationController?.popViewControllerAnimated(true)
}
}
Tenga en cuenta que el protocol
está fuera de la clase View Controller.
Eso es. Al ejecutar la aplicación ahora, debería poder enviar datos desde el segundo controlador de vista al primero.
Un método más corto y simple que el protocolo / delegado es crear un cierre:
Para enviar un String en mi caso. En ViewControllerA:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewControllerB = segue.destination as? ViewControllerB {
viewControllerB.callback = { message in
//Do what you want in here!
}
}
}
En ViewControllerB:
var callback : ((String) -> Void)?
@IBAction func done(sender: AnyObject) {
callback?("Hi")
self.dismiss(animated: true, completion: nil)
}
Así es como lo haría.
@interface ViewControllerA:UIViewController
@property(strong, nonatomic) ViewControllerB * recieverB;
@end
@implementation ViewControllerA
//implement class
- (void)prepareForSegue:(UIStoryboardSegue *) sender:(id)sender
{
segue.destinationViewController.recieverA = self;
}
-(void)viewDidLoad
{
//stop strong refrence cycle
self.viewControllerB = nil;
}
@end
Clase B
@interface ViewControllerB:UIViewController
@property(strong, nonatomic, getter = parentClass) ViewControllerB * recieverA;
@end
@implementation ViewControllerB
//implement class
- (void)viewWillDisappear:(BOOL)animated
{
parentClass.recieverB = self;
//now class A will have an instance on class b
}
@end
No puse el #import
Como respondió Erhan Demirci, puedes usar delegados. Los delegados son útiles cuando quiere pasar datos a un único controlador de vista.
NSNotificationCenter
es otra forma conveniente de transferir datos entre viewcontrollers / objects. Esto es muy útil para transmitir datos dentro de la aplicación.
lee la documentación here .
El delegado personalizado es la mejor opción para mover datos, pero puedes probar esto también.
Puede usar NSUserDefaults para mover los datos donde quiera.
Código Swift 3
UserDefaults.standard.set(<Value>, forKey: <Key>)
// To set data
UserDefaults.standard.object(forKey: <Key>)
// To get data
También puede usar NSNotification para mover datos.
NotificationCenter.default.post(name: Notification.Name(rawValue: "refresh"), object: myDict)
NotificationCenter.default.addObserver(self, selector: #selector(refreshList(_:)), name: NSNotification.Name(rawValue: "refresh"), object: nil)
Puedes usar un delegado. Por lo tanto, en su ViewController B necesita crear un protocolo que envíe datos a su ViewController A. Su ViewController A se convertiría en un delegado de ViewController B.
Si eres nuevo en el objetivo C, mira lo que es delegado .
Crear protocolo en ViewControllerB.h:
#import <UIKit/UIKit.h>
@protocol senddataProtocol <NSObject>
-(void)sendDataToA:(NSArray *)array; //I am thinking my data is NSArray, you can use another object for store your information.
@end
@interface ViewControllerB : UIViewController
@property(nonatomic,assign)id delegate;
ViewControllerB.m
@synthesize delegate;
-(void)viewWillDisappear:(BOOL)animated
{
[delegate sendDataToA:yourdata];
}
en su ViewControllerA: cuando vaya a ViewControllerB
ViewControllerA *acontollerobject=[[ViewControllerA alloc] initWithNibName:@"ViewControllerA" bundle:nil];
acontollerobject.delegate=self; // protocol listener
[self.navigationController pushViewController:acontollerobject animated:YES];
y define tu función:
-(void)sendDataToA:(NSArray *)array
{
// data will come here inside of ViewControllerA
}
Editado:
Puede ver este ejemplo: Cómo puede pasar los datos al controlador de vista anterior: enlace Tutorial
Editar: Usa la solución de @ Erhan arriba. Este no. Esta no es una buena solución.
Esto ayudará. Escribe esto en tu ViewControllerB.
// Get array of current navigation stack
NSArray *arrayViewControllers = [self.navigationController viewControllers];
// Get previous viewController object from it
YOUR_VIEW_CONTROLLER_NAME *objViewController = (YOUR_VIEW_CONTROLLER_NAME *)[arrayViewControllers objectAtIndex:arrayViewControllers.count-2];
// For safety this check is needed. whether it the class that you want or not.
if ([objViewController isKindOfClass:[YOUR_VIEW_CONTROLLER_NAME class]])
{
// Access properties of YOUR_VIEW_CONTROLLER_NAME here
objViewController.yourProperty = YOUR_VALUE;
}