【问题标题】:How to Pass Values between Multiple View Controllers using Delegate / Protocol如何使用委托/协议在多个视图控制器之间传递值
【发布时间】:2015-10-18 11:41:30
【问题描述】:

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

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

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

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

下面是First VC和Third 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];
    }
}

【问题讨论】:

标签: ios objective-c delegates protocols


【解决方案1】:

是的,可以这样做。为了从 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.
    }

}

【讨论】:

    【解决方案2】:

    上面的代码没有显示您在UIViewController 中设置委托的位置。这可能就是为什么它是 nil 以及为什么你的委托方法永远不会被触发的原因。在初始化 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];
    

    【讨论】:

    • 但是我不想直接推送到第三个VC,我只是想让用户在第三个VC中更改一些操作,然后当用户返回到第一个VC时,他可能会看到更改由第三个VC触发
    • 是的,但你是说代表总是零。那是因为你没有在创建 VC 之前设置它。
    • 哦~~~刚刚忘记复制第三个VC的.h文件了,我设置在第三个VC的.h文件中:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 2014-04-23
    相关资源
    最近更新 更多