【问题标题】:trying to understand protocols and delegates in swift试图快速理解协议和委托
【发布时间】:2015-01-13 19:22:42
【问题描述】:

我正试图围绕协议和委托进行思考,但似乎遇到了一些问题。我有 2 个试图从中传递数据的 ViewController。 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)
        }
    }

这里不允许我在协议中设置 player Name 属性。当我从 ViewController A 检查它时,它一直返回 Nil。

视图控制器 A 如下所示:

    class A-ViewController: UIViewController, UITextFieldDelegate, AddPlayersViewControllerDelegate{

var addPlayerDelegate:AddPlayersViewControllerDelegate?
}

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

覆盖 func viewWillAppear(animated: Bool) {

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

}

我确信我没有完全理解某些东西,但我觉得我只是继续阅读和尝试示例,最终回到我开始的地方。

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

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

VC-A 有一个文本字段和一个按钮。 VC-B 有一个表格视图。我希望选择从 CB-B 的 cell.text 填充 textField,但前提是用户点击按钮查看 VC-B。所以第一次加载 VC-A 时,它应该从协议中的 playerName 字符串返回 nil,因为到目前为止还没有调用 VC-B。但是一旦用户点击 VC-A 内的按钮查看 VB-B 然后选择一个单元格,这将关闭 VC-B 并在 VC-B 类的协议内填充 playerName 字符串,然后我使用 viewWillAppear检查是否设置了 playerName 的方法,如果设置了,请使用它。这是您提供的帮助中我更新的代码。

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 类。这有意义吗?

【问题讨论】:

    标签: ios swift delegates protocols


    【解决方案1】:

    您已经证明在 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 协议。事实上,令我惊讶的是,如果没有该属性,您的代码甚至可以编译。您确定您的报告正确吗?

    【讨论】:

    • 顺便说一下,这里有一个可下载的示例项目,它在 Swift 中完整正确地显示了协议/委托模式:github.com/mattneub/Programming-iOS-Book-Examples/tree/master/… 我建议你只是盲目地复制它,直到你理解它为止。
    • Matt,感谢您的帮助,我一直在查看您的示例文件,但仍有一些问题,我更新了上面的问题并输入了我正在使用的新代码,没有错误但仍然每次只能返回零。
    • 看来你甚至不了解类和实例。第一个代码中提到的 LookupViewController 不是运行第二个代码的那个。
    • 不,我理解类和实例。你怎么会这么说?我正在尝试简化我的代码,以使其不至于看太多。在一个非常高的层次上,我只想从 VC-B 中获取一个 var 并在 VC-A 中使用它,但我知道第一次 VC-B 将不存在,直到用户单击该按钮以初始化该视图.没关系,我可以从那个 var 中检查 nil。
    • 请记住,您是在这里遇到麻烦的人。 “我确定我没有完全理解某些事情。”那是真实的。我告诉你它是什么。您不明白每次实例化一个类时都会得到一个不同的 实例。如果你这样做了,你就不会说let svc = LookUpViewController()svc.addPlayerDelegate = self 来期待有意义的事情发生。这个svc和“用户点击按钮查看VC-B”时会出现的LookUpViewController不一样,所以你还没有建立B到A的通信线路。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多