如何使用委托/协议在多个视图控制器之间传递值

时间:2015-07-28 04:37:34

标签: ios objective-c delegates protocols

基本上,我现在打算使用委托在视图控制器之间传递值。

视图控制器的流程是A - > B - > ç

当用户在“C”视图控制器中执行某些操作时,如何将值传递回第一个视图控制器,即“A”?

在我自己的代码中,委托方法永远不会被触发,“self.delegate”总是“null”。我不知道为什么以及如何解决这个问题。

以下是第一个VC和第三个VC的代码:

#import "ViewController.h"
#import "ThirdViewController.h"

@interface ViewController ()<PassValueProtocal>
@property (weak, nonatomic) IBOutlet UILabel *myLabel;

@end

@implementation ViewController
{
    ThirdViewController *thirdVC;
}

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

- (void) passValueBack:(NSString *)value
{
    NSLog(@"HAHAH");
}

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


- (IBAction)segueToSecondVC:(UIButton *)sender
{
    thirdVC = [ThirdViewController sharedManager];
    thirdVC.delegate = self;
}

@end

#import "ThirdViewController.h"

@interface ThirdViewController ()
@property (weak, nonatomic) IBOutlet UITextField *myTextField;

@end

@implementation ThirdViewController

+ (id) sharedManager
{
    NSLog(@"myDelegate sharedManager");
    static ThirdViewController *sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{ sharedManager = [[self alloc] init]; });
    return sharedManager;
}

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

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

- (IBAction)passValueAction:(UIButton *)sender
{
    NSLog(@"%@", self.delegate);
    if ([self.delegate respondsToSelector:@selector(passValueBack:)])
    {
        [self.delegate passValueBack:self.myTextField.text];
    }
}

2 个答案:

答案 0 :(得分:0)

上述代码未显示您在UIViewController中设置代理的位置。这可能就是为什么它为零,也是为什么你的委托方法永远不会被解雇的原因。初始化UIViewController之后但在推送之前设置委托属性:

// Inside your third viewcontroller class:
@interface ThirdViewController ()
@property (weak, nonatomic) id delegate; // make sure the delegate is set to weak
@end


// Maybe in your AppDelegate, before you push the third view controller
ThirdViewController *thirdVC = [[ThirdViewController alloc] init];
thirdVC.delegate = self;
// Now push the VC. The below assumes a UINavigationController but that detail isn't important.
[self.navigationController pushViewController:thirdVC animated:YES];

答案 1 :(得分:0)

是的,这是可能的。为了从C传递数据 - > A,你需要链接代表

故事板的外观如下:http://i.imgur.com/9PXdlno.png?1

在故事板中注意 segue标识符

<强> FirstViewController:

import UIKit

class FirstViewController: UIViewController, SecondViewControllerDelegate {

    @IBAction func buttonPressed(sender: AnyObject) {
        performSegueWithIdentifier("goToSecondView", sender: self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if(segue.identifier == "goToSecondView"){
            let secondVC: SecondViewController = segue.destinationViewController as! SecondViewController

            secondVC.delegate = self
        }
    }

    func speakSecond(name: String) {
        print("Data from Third view is: \(name)")
    }
}

<强> SecondViewController:

import UIKit

protocol SecondViewControllerDelegate{
    func speakSecond(name: String)
}


class SecondViewController: UIViewController, ThirdViewControllerDelegate {

    var delegate: SecondViewControllerDelegate?

    @IBAction func buttonPressed(sender: AnyObject) {
        performSegueWithIdentifier("goToThirdView", sender: self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if(segue.identifier == "goToThirdView"){
            let thirdVC: ThirdViewController = segue.destinationViewController as! ThirdViewController
            thirdVC.delegate = self
        }
    }

    func speakThird(name: String) {
        delegate?.speakSecond(name)
    }
}

<强> ThirdViewController:

import UIKit

protocol ThirdViewControllerDelegate{
    func speakThird(name: String)
}

class ThirdViewController: UIViewController {

    var delegate: ThirdViewControllerDelegate?

    @IBOutlet var textField: UITextField!

    @IBAction func buttonPressed(sender: AnyObject) {
        let text = textField.text
        delegate?.speakThird(text)
        self.navigationController?.popToRootViewControllerAnimated(true)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}