使用委托/协议将数据传递给第三方视图控制器

时间:2015-09-28 01:10:50

标签: ios swift delegates protocols

我有3个视图控制器:http://i58.tinypic.com/2envu2x.png

视图控制器1是第一个,并且它被视为视图控制器2.视图控制器3是视图控制器2的子视图,因为在视图控制器2中存在容器视图。我需要将数据从视图控制器1传递到视图控制器3.使用传统的委托和协议,我必须实际上看到控制器3才能将数据传递给它。但是segue是从第一个视图控制器到容器视图(第二个视图控制器),而不是第三个。如何修改委托/协议来实现这一目标?

这是我的第一个视图控制器的代码(它有一个表视图,所以我将协议放在表格单元格中):

import UIKit

 protocol DataEnteredDelegate {
func userDidCHooseClass(classChose: String)
}

class FirstTableViewCell: UITableViewCell {

var delegate:DataEnteredDelegate?
@IBAction func buttonTapped(sender: AnyObject) {

    let string = "che107"
    self.delegate?.userDidCHooseClass(string)
}




override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
   }

}

以下是视图控制器3的代码,我想要接收字符串的视图控制器:

  import UIKit

class SecondTBC: UITableViewController, DataEnteredDelegate {

var stringThing = String()

override func viewDidLoad() {
    super.viewDidLoad()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem()




}

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

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 0
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.
    return 0
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! firstCell



    return cell
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "segue1" {
        var otherController = FirstTableViewCell()
        otherController.delegate = self
    }
}


       func userDidCHooseClass(classChose: String) {
    stringThing = classChose
   }

}

2 个答案:

答案 0 :(得分:1)

要在两个未连接的视图控制器之间传递数据,您需要使用:

presentingViewController!.dismissViewControllerAnimated(true, completion: nil)

并通过viewWillDisappear传输您的数据,如下所示:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    if self.isBeingDismissed() {
        self.delegate?.acceptData(textFieldOutlet.text)
    }
}

我发布了a tutorial,其中包含一个可以下载和检查的工作项目文件。

下面是上下文中模式的一个例子。

ViewController 2:

// place the protocol in the view controller that is being presented
protocol PresentedViewControllerDelegate {
    func acceptData(data: AnyObject!)
}

class PresentedViewController: UIViewController {
    // create a variable that will recieve / send messages
    // between the view controllers.
    var delegate : PresentedViewControllerDelegate?
    // another data outlet
    var data : AnyObject?


    @IBOutlet weak var textFieldOutlet: UITextField!
    @IBAction func doDismiss(sender: AnyObject) {
        if textFieldOutlet.text != "" {
            self.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        print("\(data!)")

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

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


    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        if self.isBeingDismissed() {
            self.delegate?.acceptData(textFieldOutlet.text)
        }
    }

}

ViewController 1:

class ViewController: UIViewController, PresentedViewControllerDelegate {

    @IBOutlet weak var textOutlet: UILabel!
    @IBAction func doPresent(sender: AnyObject) {
        let pvc = storyboard?.instantiateViewControllerWithIdentifier("PresentedViewController") as! PresentedViewController

        pvc.data = "important data sent via delegate!"
        pvc.delegate = self
        self.presentViewController(pvc, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    func acceptData(data: AnyObject!) {     
        self.textOutlet.text = "\(data!)"

    }
}

答案 1 :(得分:0)

我找到了答案:使用全局变量。

这是我做的:

在我的第一个视图控制器(发送字符串的视图控制器)中,我在类定义之上创建了一个全局变量,如下所示:

 import UIKit

 var chosenClass = String()

 class EntryViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

// other code here that isn't relevant to the topic at hand

}

然后,在同一视图控制器中,当选择表格单元格时,我这样做了:

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {


    var row = self.tableView.indexPathForSelectedRow()?.row
    chosenClass = array2[row!]




}

其中

 array2[row!]

是我想传递的字符串。

在第三个视图控制器中,我创建了另一个字符串局部变量,字符串接收:

import UIKit
import Parse
import ParseUI
import Foundation

 class FirstTableViewController: PFQueryTableViewController {


@IBOutlet weak var navigationBarTop: UINavigationItem!

var stringToRecieve = String()

}

在第三个视图控制器的viewDidLoad中,我只是简单地说:

stringToRecieve = chosenClass

就是这样。第二个视图控制器不需要额外的代码,容器视图是。