使用协议传递数据而无需返回原始控制器

时间:2016-10-23 16:26:29

标签: ios swift delegates protocols

我一直在研究代表团的工作方式。您可以在控制器A中定义协议,创建委托变量,并通过委托调用该函数。然后,在控制器B中,您遵循协议,实现方法,然后使用prepareForSegue告诉控制器A控制器B是委托。

但这涉及A - > B - >答:我需要知道如何做A - > B.我一直在尝试通过以下代码执行此操作:

在控制器A中声明协议

protocol CellDataDelegate {

    func userDidTapCell(data: String)
}

在A

中创建委托变量
var cellDelegate: CellDataDelegate? = nil

在单击“

”时调用A中代理中的函数
if cellDelegate != nil {

    let cellKey = keys[indexPath.row].cellKey
    cellDelegate?.userDidTapCell(data: cellKey)

    self.performSegue(withIdentifier: "showDetails", sender: self)
}

将委托添加到控制器B并符合方法

class DetailsVC: UIViewController, CellDataDelegate

功能:

func userDidTapCell(data: String) {

    useData(cellKey: data)
}

这里的问题是授权过程的最后一部分。我无法使用prepareForSegue来执行controllerA.delegate = self部分,因为我不想回到控制器A,我需要留在控制器B. 那么如何告诉控制器A B是代表吗?

3 个答案:

答案 0 :(得分:1)

协议代理通常用于将数据传递到先前的UIViewController而不是导航堆栈中的当前UIViewController(在popViewController的情况下),因为要将数据发送到的UIViewController需要存在于内存中。在你的情况下,你没有在内存中初始化UIViewController B,以便执行协议委托的方法。

有一些简单的方法可以将数据发送到导航堆栈中的下一个UIViewControllers。

您的UIViewController B应该有一个接收变量来存储从UIViewController A发送的数据

class DestinationVC : UIViewController
{
    receivingVariable = AnyObject? // can be of any data type depending on the data
}

方法1:使用Storyboard ID

let destinationVC = self.storyboard.instantiateViewControllerWithIdentifier("DestinationVC") as DestinationVC 
destinationVC.receivingVariable = dataInFirstViewControllerToBePassed
self.navigationController.pushViewController(destinationVC , animated: true)

方法2:使用prepareForSegue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
{
    let destinationVC = segue.destinationViewController as DestinationVC 
    destinationVC.receivingVariable = dataInFirstViewControllerToBePassed
}

从UIViewController A到任何其他UIViewController的多个segue将导致每次执行prepareForSegue并且可能使应用程序崩溃,因为其他类的UIViewControllers将没有诸如UIViewController中存在的 receivingVariable 之类的参数B. 这很容易抵消;可以使用segue.identifier上的if else或switch模块简单地使用多个segue。

注意: UILabel,UIButton和另一个UI元素的属性不能以这种方式分配,因为这些元素在UIViewController生命周期的 func loadView()内存中加载因为当你初始化UIViewController B的类时,它们没有设置为初始化。

答案 1 :(得分:0)

我认为你不需要在这里使用委托模式。如果你想要实现这一点。您在视图控制器A上有一些单元格,现在要在视图控制器B中显示单元格的详细信息(单击时)。您可以将单元格键声明为视图控制器B中的属性。

class B: UIViewController {
    let cellKey: String!
}

并在准备segue方法

中设置上述键
if (segue.identifier == "segueToViewControllerB") {
    let vc = segue.destinationViewController as B
    vc.cellKey= "1"
}

答案 2 :(得分:0)

我认为你误解了你提到的问题的重点。上面的问题详细解释了发生了什么,但这里有一个简短的答案,对于那些懒惰的人:不要准备ForSegue从底部到顶部传递信息(即从子视图控制器到父级),但大多数情况下肯定请用它从上到下传递。