试图在swift中理解协议和委托

时间:2014-11-16 23:19:29

标签: ios swift delegates protocols

我试图绕过协议和代表,但似乎遇到了一些问题。我有2个ViewControllers,我试图从中传递数据。 ViewController A有一个文本字段,我希望可以从ViewController B中选择填充。所以ViewController A上有一个按钮可以将你调到ViewController B这就是我设置B的方式。

 protocol AddPlayersViewControllerDelegate{
    var playersName:String? { set get }
}

class B-Controller: UIViewController, UITableViewDelegate, UITableViewDataSource{

    var addPlayerDelegate:AddPlayersViewControllerDelegate?

    override func viewDidLoad() {
            super.viewDidLoad()
    ..etc

    }

我在viewControllers B类中使用此代码在选择单元格时关闭currentView

   func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {


        println("did select")
        let cell = playerTableView.cellForRowAtIndexPath(indexPath)

        addPlayerDelegate?.playersName? = "New Name"

        if let navController = self.navigationController {
            navController.popViewControllerAnimated(true)
        }
    }

它不允许我在此处设置协议内的玩家名称属性。当我从ViewController A中检查它时,它一直让我返回Nil。

View Controller A看起来像这样:

    class A-ViewController: UIViewController, UITextFieldDelegate, AddPlayersViewControllerDelegate{

var addPlayerDelegate:AddPlayersViewControllerDelegate?
}

//然后我只是试图打印出在ViewController B中设置的新名称

覆盖func viewWillAppear(动画:Bool){

println("this is the selected players name \(addPlayerDelegate?.playersName)") - returns nil

}

我确定我没有完全理解某些内容,但我觉得我只是继续阅读并尝试了一些示例,但最终还是在我开始的地方结束。

// *************************更新******************* ****** //

我将尝试简化我的设置。我有2个视图控制器,VC-A和VC-B。

VC-A有一个文本字段和一个按钮。 VC-B有一个tableview。我希望选项可以从CB-B的cell.text中填充textField,但前提是用户点击按钮查看VC-B。所以第一次加载VC-A时,它应该从协议中的playersName字符串返回nil,因为VC-B从未被调用过。但是一旦用户点击VC-A内的按钮来查看VB-B,然后选择一个单元格,这将解散VC-B并在VC-B类的协议中填充playersName字符串,然后我使用viewWillAppear方法检查是否已设置playersName,如果是,则使用它。这是我给你的帮助中的更新代码。

VC-A

class FirstViewController: AddPlayersViewControllerDelegate{

    var playersName:String?

    let svc = LookUpViewController()

    override func viewDidLoad() {
        super.viewDidLoad()

        svc.addPlayerDelegate = self
    }
}

VC-B

protocol AddPlayersViewControllerDelegate{
    var playersName:String? { set get }
}


class LookUpViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{

    var addPlayerDelegate: AddPlayersViewControllerDelegate?  
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}


    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        let cell = playerTableView.cellForRowAtIndexPath(indexPath)

        addPlayerDelegate?.playersName = "Ziggy"


        println("the name to be pass is \(addPlayerDelegate?.playersName)")

        if let navController = self.navigationController {
            navController.popViewControllerAnimated(true)
        }
    }

即使我从VC-B回到VC-A,似乎我仍然没有。我想要的是能够从VC-B获取一些数据(字符串)并在VC-A中使用它,但仅在用户使用VC-B类之后。这有意义吗?

1 个答案:

答案 0 :(得分:4)

您已经证明,在BController中您有一个属性addPlayerDelegate

var addPlayerDelegate:AddPlayersViewControllerDelegate?

你已经证明,在BController中你可以和那个属性交谈:

addPlayerDelegate?.playersName? = "New Name"

但是你没有证明在这个控制器的生命周期的任何一点,它的addPlayerDelegate属性都设置到任何东西。例如,我希望看到这样的代码:

someBController.addPlayerDelegate = someAController

如果没有发生,那么该属性保持其初始值为nil。


你的代码的另一个问题是这条线毫无意义:

class A-ViewController : // {
    var addPlayerDelegate:AddPlayersViewControllerDelegate?
}

AController不需要这个属性。他们不两个需要代表! AController需要的是playersName属性。没有它,它不符合AddPlayersViewControllerDelegate协议。事实上,我很惊讶没有那个属性你的代码甚至可以编译。您确定要正确报告吗?