iOS Swift - 协议(protocol)发送委托(delegate)给错误的 TableViewController

标签 ios swift delegates protocols

我有一个带有 TableViewController 链的应用程序,由通知 Controller 链接,从网络服务检索信息。下一个表中的数据是从网络服务中提取的,与上一个表中选择的数据有关。当我拉出任何表进行刷新时,它会再次请求信息,协议(protocol)会向 TableView 发送委托(delegate)消息以刷新信息。

嗯,到目前为止还不错。但是,我遇到了一些奇怪的事情......示例:我在 tableView #2 上,然后使用导航后退按钮转到上一个表 #1。当在 #1 上,我拉动 tableview 进行刷新时,它崩溃并给我一个“无法识别的选择器发送到实例”告诉我 Tableview #2 没有可选的委托(delegate)方法,用于获取信息以填充 TableView #1。而且我什至不再使用 TableView #2,iOS 将委托(delegate)消息发送到错误的 ViewController,因为当单击 NavigationController backButton 时 tableViewController 甚至没有被关闭......

有人体验过吗?我知道这看起来有点困惑,但事实就是如此。

让我们在这里获取一些代码: 两个 TableViewController:ClientsViewController 和 ProjectsViewController 当您在 ClientsViewController 表上选择一个客户端时,它会从该客户端加载 ProjectsViewController 表上的所有项目。

客户端 View Controller

override func viewDidLoad() {
        super.viewDidLoad()
        wsCommHandler.delegate = self
        self.tableView.delegate = self
        self.tableView.dataSource = self

        self.refreshControl!.addTarget(self, action: Selector("refreshClients:"), forControlEvents: UIControlEvents.ValueChanged)
        wsCommHandler.getClients()

    }

    func refreshClients(sender:AnyObject){
        println("Refreshing")
        self.refreshControl?.beginRefreshing()
        wsCommHandler.getClients()
        self.refreshControl?.endRefreshing()
    }

func didReceiceResponseFromGetClientsRequest(response: [AnyObject]) {
        self.clients = response
        self.tableView.reloadData()

    }

wsCommHandler“getClients()”从网络服务中检索所有客户端,并使用委托(delegate)“didReceiceResponseFromGetClientsRequest”重新加载表。

当一个客户端被选中时,它会转到下一个 TableViewController,在 ViewController 之间传递一个 client_id。

这是来自 ProjectsViewController 的代码示例

override func viewDidLoad() {
        super.viewDidLoad()
        wsCommHandler.delegate = self
        self.tableView.delegate = self
        self.tableView.dataSource = self

        self.refreshControl!.addTarget(self, action: Selector("refreshProjects:"), forControlEvents: UIControlEvents.ValueChanged)
        wsCommHandler.getProjectsByClient(client_id) 
    }

    func refreshProjects(sender:AnyObject){
        println("Refreshing")
        self.refreshControl?.beginRefreshing()
        wsCommHandler.getProjectsByClient(client_id)
        self.refreshControl?.endRefreshing()
    }

    func didReceiceResponseFromGetProjectsRequest(response: [AnyObject]) {
        self.projects = response
        self.tableView.reloadData()

    }

它以与客户端相同的方式在屏幕上加载项目,但现在使用委托(delegate)“didReceiceResponseFromGetProjectsRequest”

现在,如果我按下导航 Controller 后退按钮,它会将 ClientsViewController 带回到前面(无需重新加载)...当我拉动它进行刷新时。该类被调用,检索数据,然后:崩溃!

2015-03-06 09:26:18.978 PostItHours[9174:792018] -[PostItHours.ProjectsViewController didReceiceResponseFromGetClientsRequest:]: 无法识别的选择器发送到实例 0x7fe0c4132c30 2015-03-06 09:26:18.980 PostItHours[9174:792018] 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[PostItHours.ProjectsViewController didReceiceResponseFromGetClientsRequest:]:无法识别的选择器发送到实例 0x7fe0c4132c30”

正如你们所看到的,它正试图在 ProjectsViewController 上执行此操作,该 Controller 已被后退按钮关闭。

有什么想法吗?

最佳答案

我试过了,它对我有用。 2 个 View Controller ,每个都有不同的数据源,两者之间有一个“toSecondVC”segue。

View Controller :

import UIKit

class ViewController: UITableViewController {
    var texts = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        texts.append("viewController")
        self.title = "viewController"
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        refreshControl = UIRefreshControl()
        refreshControl!.addTarget(self,
            action: "handleRefresh:",
            forControlEvents: .ValueChanged)

        tableView.addSubview(refreshControl!)

    }

    func handleRefresh(paramSender: AnyObject){
        //pause it 1 sec
        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC))
        dispatch_after(popTime,
            dispatch_get_main_queue(), {
                self.texts.append(String("viewController-\(self.texts.count+1)"))
                self.refreshControl!.endRefreshing()
                let indexPathOfNewRow = NSIndexPath(forRow: self.texts.count - 1,
                    inSection: 0)

                self.tableView!.insertRowsAtIndexPaths([indexPathOfNewRow],
                    withRowAnimation: .Automatic)
        })
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "toSecondVC" {
            let viewController:SecondVC = segue.destinationViewController as SecondVC
            let indexPath = self.tableView.indexPathForSelectedRow()
            viewController.stringSelected = texts[indexPath!.row]
        }
    }

    //MARK : TableView Delegate
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        cell.textLabel.text = texts[indexPath.row]
        return cell
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return texts.count
    }
}

第二个VC:

import UIKit

class SecondVC: UITableViewController {
    var texts = [String]()
    var stringSelected = String()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "secondVC"
        texts.append("secondVC")
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        refreshControl = UIRefreshControl()
        refreshControl!.addTarget(self,
            action: "handleRefresh:",
            forControlEvents: .ValueChanged)

        tableView.addSubview(refreshControl!)

        println("stringSelected : \(stringSelected)")
    }

    func handleRefresh(paramSender: AnyObject){

        //pause it 1 sec
        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC))
        dispatch_after(popTime,
            dispatch_get_main_queue(), {
                self.texts.append(String("secondVC-\(self.texts.count+1)"))
                self.refreshControl!.endRefreshing()
                let indexPathOfNewRow = NSIndexPath(forRow: self.texts.count - 1,
                    inSection: 0)

                self.tableView!.insertRowsAtIndexPaths([indexPathOfNewRow],
                    withRowAnimation: .Automatic)

        })

    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        cell.textLabel.text = texts[indexPath.row]
        return cell
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return texts.count
    }


}

关于iOS Swift - 协议(protocol)发送委托(delegate)给错误的 TableViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28897124/

相关文章:

ios - iOS 中的自定义 View 类未调用委托(delegate)事件

delegates - UITextField,1个字符后自动移至下一个

ios - 报告 UIView 子类所需大小的正确方法是什么?

ios - 如何根据 iPhone 向上移动文本字段。 swift 大小

c# - C#(或其他语言)中委托(delegate)的使用

ios - 快速更改 titleTextAttribute

ios - Storyboard 和 xib 不显示新添加的元素

ios - swift 3.0 : How to save a user's image in the app from an imagePicker

ios - 使用 prepareForSegue 显示从 MasterViewController 到 DetailViewController 的字符串

带有基本身份验证的 iOS swift Web 服务调用