1

I have viewController1 that makes a modal segue to my viewController2 but the

viewController2 is embebed on a navigation controller

because I need the navigation bar there.

I've implemented a protocol to send the data back from viewController2 to viewController1 but it doesn't function. Here is my code:

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

    }
}

On the viewController2 I have this:

class viewController2: UIViewController{
    var delegate: writeValueBackDelegate?

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

I dont know why but it functions only if I remove the navigation controller from my secondviewController and make the segue from viewController 1 to viewController 2 directly, but I need the navigation controller to show the navigation bar.

Do you know why it is happening? or Why I'm doing bad.

4

2 回答 2

1

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

ViewController1 -> NavigationController -> ViewController2

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

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

您在那里的向下转型将失败,因为目标 V​​C 不是 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 中:在适当的时间发布通知。 NSNotificationCenter.defaultCenter().postNotificationName("SomeName", object: nil, userInfo: ["theKey":"theData"])
于 2015-11-17T04:44:50.413 回答
0

这是通过 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。

因此,您需要在 ViewControllerB 的按钮操作方法中设置postNotificationName以获取数据。

接下来,您需要在 ViewControllerA 中编写addObserver(将数据发送到所需的视图控制器),并在同一视图控制器中调用 addObserver 方法。

让我们看看使用 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.
}

在视图控制器中

。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 方法。

首先我们需要在 ViewControllerB.h 中设置分配委托

非常重要的是,我们必须在ViewControllerB中设置自定义委托方法,因为一旦我们单击 ViewControllerB 中的操作按钮,我们就会将数据发送到 ViewControllerA。

最后,我们必须在View ControllerA中调用Custom Delegate 方法,在这里我们获取数据并将该数据分配给标签。现在您可以使用自定义委托查看传递的数据(从 ViewControllerB 到 ViewControllerA)。

同样,您可以使用自定义委托方法或 NSNotificationCenter将数据发送到其他视图控制器

于 2015-11-17T07:46:37.020 回答