Pass data back to previous viewcontroller

2019-01-02 14:52发布

I am trying to pass data BACK TO previous viewController.

Does anyone know how to pass data back from ViewController B to ViewController A? So I want a string to go 'from' BIDAddTypeOfDealViewController to BIDDCCreateViewController. A user edits viewController B and I want that edited data back in ViewController A where I then use it.

I am using the 'passing data back' section of this answer. How mine differs: Point 3 and 6 just mentions when views are popped so I have put that code in viewWillDisappear. I think that is correct? Also on Point 6 I did not initialise with nib as that is old. I'm using storyboards. And I did not add that last line as I do not believe I would have to push it. Pressing a button on my storyboard already takes me forward.

I think the problem may arise in BIDDCCreateViewController, I have the method but I cannot run it. To run a method it should go [self method]. I am unable to do that. Well that is just what I am guessing.

It compiles and runs fine just nothing is logged, so I don't know if it works.

UPDATE: I am unable to get the 'sendDataToA' method to execute.

#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

8条回答
只靠听说
2楼-- · 2019-01-02 15:22

Swift: Sending data back using the delegate pattern

My full answer that covers passing data both ways is here. My answer explaining the delegate pattern is here.

To pass data back from the second view controller to the first view controller, you use a protocol and a delegate. This video is a very clear walk though of that process:

The following is an example based on the video (with a few modifications).

enter image description here

Create the storyboard layout in the Interface Builder. Again, to make the segue, you just Control drag from the button to the Second View Controller. Set the segue identifier to showSecondViewController. Also, don't forget to hook up the outlets and actions using the names in the following code.

First View Controller

The code for the First View Controller is

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
    }
}

Note the use of our custom DataEnteredDelegate protocol.

Second View Controller and Protocol

The code for the second view controller is

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)
    }
}

Note that the protocol is outside of the View Controller class.

That's it. Running the app now you should be able to send data back from the second view controller to the first.

查看更多
听够珍惜
3楼-- · 2019-01-02 15:23

You can use a delegate. So in your ViewController B you need to create a protocol that sends data back to your ViewController A. Your ViewController A would become a delegate of ViewController B.

If you are new to objective C, please look at What is Delegate.

Create protocol in 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];

}

in your ViewControllerA : when you go to ViewControllerB

ViewControllerA *acontollerobject=[[ViewControllerA alloc] initWithNibName:@"ViewControllerA" bundle:nil];
acontollerobject.delegate=self; // protocol listener
[self.navigationController pushViewController:acontollerobject animated:YES];

and define your function:

-(void)sendDataToA:(NSArray *)array
{
   // data will come here inside of ViewControllerA
}

Edited :

You can See this example : How you can Pass data back to previous viewcontroller: Tutorial link

查看更多
何处买醉
4楼-- · 2019-01-02 15:25

Custom delegate is the best option to move data but you can try this also.

You can use NSUserDefaults for Moving the data any where you want.

Swift 3 Code

UserDefaults.standard.set(<Value>, forKey: <Key>) 
// To set data

UserDefaults.standard.object(forKey: <Key>) 
// To get data

You can also use NSNotification for move data.

NotificationCenter.default.post(name: Notification.Name(rawValue: "refresh"), object: myDict) 

NotificationCenter.default.addObserver(self, selector: #selector(refreshList(_:)), name: NSNotification.Name(rawValue: "refresh"), object: nil)
查看更多
泪湿衣
5楼-- · 2019-01-02 15:36

A shorter and simpler method than protocol/delegate is to create a closure:

For sending a String back in my case. In 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!
        }
    }
}

In ViewControllerB:

var callback : ((String) -> Void)?

@IBAction func done(sender: AnyObject) {
    callback?("Hi")
    self.dismiss(animated: true, completion: nil)
}
查看更多
忆尘夕之涩
6楼-- · 2019-01-02 15:40

As Erhan Demirci answered, you can use delegates. Delegates are helpful when you want to pass data to a single view controller.

NSNotificationCenter is another convenient way to transfer data between viewcontrollers/objects. This is very helpful in broadcasting data within the application.

read documentation here.

查看更多
怪性笑人.
7楼-- · 2019-01-02 15:44

Here is how I would do it.

@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

Class 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

I didn't put the #import

查看更多
登录 后发表回答