iOS 使用 presentModalSegue 将数据从 viewController2 传回 viewController1

iOS Pass data back from viewController2 to viewController 1 with presentModalSegue

我有 viewController1 对我的 viewController2 进行模态转换,但是

viewController2 is embebed on a navigation controller

因为我需要那里的导航栏。

我已经实现了一个将数据从 viewController2 发送回 viewController1 的协议,但它不起作用。这是我的代码:

protocol writeValueBackDelegate {
    func writeValueBack(value: String)
}

class viewController1: UITableViewController, writeValueBackDelegate {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "SelectAddress"{
            if let dest = segue.destinationViewController as? MapAddressViewController{
                dest.delegate = self
            }
        }

    }
}

在 viewController2 我有这个:

class viewController2: UIViewController{
    var delegate: writeValueBackDelegate?

@IBAction func TaskOneClick(sender: AnyObject) {
        delegate?.writeValueBack(txtAddress!.text!)
        self.navigationController?.popViewControllerAnimated(true)
    }
}

我不知道为什么,但只有当我从我的第二个 viewController 上移除导航控制器并直接从 viewController 1 到 viewController 2 进行转场时它才会起作用,但我需要导航控制器显示导航栏。

你知道为什么会这样吗?或者为什么我做得不好。

这是我对您的设置的理解。

ViewController1 -> NavigationController -> ViewController2

在这种情况下,在 prepare for segue 方法中,目标 viewcontroller 是 Navigation Controller 而不是 ViewController2。 因此,这行代码不会成立。

if let dest = segue.destinationViewController as? MapAddressViewController{
            dest.delegate = self
        }

你在那里的失望会失败,因为目的地 VC 不是 MapAddressViewContoller,而是一个 UINavigation 控制器。

要解决此问题,您可以按如下方式更改代码:

if let dest = segue.destinationViewController as? UINavigationController{
            dest.rootViewController.delegate = self
        }

但是,我更喜欢使用 NSNotification 将数据向下传递回视图控制器层次结构。 你也可以试试看。

使用通知:

  • 第 1 步:在 VC1 中:注册通知。 override func viewDidLoad() { NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("myFunc:"), name: "SomeName", object: nil) } func myFunc(theNotifiction : NSNotification){ print("I got notified (theNotifiction.userInfo!)") }
    • 第 2 步:在 VC2 中:Post 在适当的时间发出通知。 NSNotificationCenter.defaultCenter().postNotificationName("SomeName", object: nil, userInfo: ["theKey":"theData"])

下面是通过 NSNotification 和 CustomDelegate 实现的方法

让我们先看看使用 NSNotification 从 ViewController2 到 ViewController1 传递数据。

在ViewControllerB

.h

#import <UIKit/UIKit.h>
@interface ViewControllerB : UIViewController  
@property (nonatomic, strong) IBOutlet UITextField *txtAddress;
- (IBAction)TaskOneClick:(id)sender;
@end

.m

#import "ViewControllerB.h"
@interface ViewControllerB ()
@end
@implementation ViewControllerB

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
   if (self) {
    // Custom initialization
   }
   return self;
}

- (void)viewDidLoad
{
     [super viewDidLoad];
     // Do any additional setup after loading the view.
}

//Using NSNotification 
- (IBAction)TaskOneClick:(id)sender;
{
          //Use NSNotificationCenter
     [[NSNotificationCenter defaultCenter] postNotificationName:@"passingDataFromSecondViewToFirstView" object:self.txtAddress.text];
     [self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning
{
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
}

在ViewControllerA

.h

#import <UIKit/UIKit.h>
#import "ViewControllerB.h"
@interface ViewControllerA : UIViewController<ViewControllerBDelegate>
@property (nonatomic, strong) IBOutlet UILabel *labelGetData; 
- (IBAction)gotoNextView:(id)sender;
@end

.m

#import "ViewControllerA.h"
@interface ViewControllerA ()
@end
@implementation ViewControllerA
- (void)viewDidLoad
{
   [super viewDidLoad];
   //addObserver here...
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFromPreviousViewControllerNotificationReceived:) name:@"passingDataFromSecondViewToFirstView" object:nil];
   // Do any additional setup after loading the view, typically from a nib.
}

//addObserver Method here....
- (void)textFromPreviousViewControllerNotificationReceived:(NSNotification *)notification
{
   // set text to label...
   NSString *string = [notification object];
   self.labelGetData.text = string;
}
- (IBAction)gotoNextView:(id)sender;
{
   //If you use storyboard
   ViewControllerB *viewControllerB = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerB"];
   //OR  If you use XIB
   ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNibName:@"ViewControllerB" bundle:nil];
   [self.navigationController pushViewController:viewControllerB animated:YES];
}
- (void)didReceiveMemoryWarning
{
   [super didReceiveMemoryWarning];
   // Dispose of any resources that can be recreated.
 }

首先,我们将视图从 ViewControllerA 导航到 ViewControllerB。

之后我们将数据从ViewControllerB发送到ViewControllerA。

在上面的代码中我们使用了 NSNotification。

So that, you need to set the postNotificationName for getting data in button action method in ViewControllerB.

Next you need to write addObserver in (sending data to your required View Controller) ViewControllerA and call the addObserver method in same View Controller.

让我们看看使用 CustomDelegate 从 ViewController2 向 ViewController1 传递数据。

 in ViewControllerB

 .h


#import <UIKit/UIKit.h>
@class ViewControllerB;
@protocol ViewControllerBDelegate <NSObject>
- (void)viewControllerB:(ViewControllerB *)viewControllerB didEnterText:(NSString *)text;
@end
@interface ViewControllerB : UIViewController
@property (nonatomic, assign)id<ViewControllerBDelegate> delegate;  
@property (nonatomic, strong) IBOutlet UITextField *txtAddress;
- (IBAction)TaskOneClick:(id)sender;
@end

.m

#import "ViewControllerB.h"
@interface ViewControllerB ()
@end
@implementation ViewControllerB

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
   if (self) {
    // Custom initialization
   }
   return self;
}

- (void)viewDidLoad
{
     [super viewDidLoad];
     // Do any additional setup after loading the view.
}

//Using Custom Delegate
- (IBAction)TaskOneClick:(id)sender;
{
     [self.delegate viewControllerB:self didEnterText:self.txtAddress.text];
     [self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning
{
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
}

在ViewController

.h

#import <UIKit/UIKit.h>
#import "ViewControllerB.h"
@interface ViewControllerA : UIViewController<ViewControllerBDelegate>
@property (nonatomic, strong) IBOutlet UILabel *labelGetData; 
- (IBAction)gotoNextView:(id)sender;
@end

.m

#import "ViewControllerA.h"
@interface ViewControllerA ()
@end
@implementation ViewControllerA
- (void)viewDidLoad
{
   [super viewDidLoad];
   // Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)gotoNextView:(id)sender;
{
   //If you use storyboard
   ViewControllerB *viewControllerB = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerB"];
   //OR  If you use XIB
   ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNibName:@"ViewControllerB" bundle:nil];
   viewControllerB.delegate = self;
   [self.navigationController pushViewController:viewControllerB animated:YES];
}

//Calling custom delegate method
- (void)viewControllerB:(ViewControllerB *)ViewControllerB didEnterText:(NSString *)text
{
   self.labelGetData.text = text; //Getting the data and assign the data to label here.
}

- (void)didReceiveMemoryWarning
{
   [super didReceiveMemoryWarning];
   // Dispose of any resources that can be recreated.
 }

在上面的代码中,我们使用了 CustomProtocolDelegate 方法。

First we need to Set and Assign the delegate in ViewControllerB.h

Very importantly we have to set the Custom Delegate Method in the ViewControllerB because where we send the data to ViewControllerA once we click the action button in ViewControllerB.

Finally we must call the Custom Delegate Method in View ControllerA, where we get the data and assign that data to label.Now you can see the passed data(From ViewControllerB to ViewControllerA) using custom delegate.

同样,您可以使用自定义委托方法或 NSNotificationCenter

将数据发送到其他视图控制器