iOS Swift - 协议将委托发送到错误的 TableViewController
iOS Swift - Protocol sending delegate to wrong TableViewController
我有一个带有 TableViewController 链的应用程序,由通知控制器链接,从网络服务检索信息。来自下一个 table 的数据是从网络服务中提取的,与前一个选择的数据有关。当我拉动任何 table 进行刷新时,它会再次请求信息,协议会向 table 视图发送委托消息以刷新信息。
嗯,到目前为止一切顺利。但是,我遇到了一些奇怪的事情...示例:我在 tableView #2 上,然后使用导航后退按钮转到上一个 table,即 #1。当在 #1 上,我拉动 table 视图进行刷新时,它崩溃并给我其中一个 "unrecognized selector sent to instance" 告诉我 Tableview #2 没有可选的委托方法,用于获取信息以填充 TableView #1。而且我什至不再使用 TableView #2,iOS 正在将委托消息发送到错误的 ViewController,因为 tableViewController 不是'单击 NavigationController backButton 时甚至被关闭...
有人体验过吗?我知道这看起来有点混乱,但这就是正在发生的事情。
让我们在这里获取一些代码:
两个 TableViewController:客户ViewController 和项目ViewController
当您 select ClientsViewController Table 上的客户端时,它会从 ProjectsViewController Table.
上的客户端加载所有项目
客户ViewController
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()' 从网络服务中检索所有客户端并使用委托 'didReceiceResponseFromGetClientsRequest' 重新加载 table。
当客户端被 selected 时,它会转到下一个 TableViewController,在 ViewController 之间传递一个 client_id。
这是项目中的代码示例ViewController
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()
}
它以与客户端相同的方式在屏幕上加载项目,但现在使用委托 'didReceiceResponseFromGetProjectsRequest'
现在,如果我按下导航控制器后退按钮,它会将 ClientsViewController 带回到前面(无需重新加载)...当我拉动它进行刷新时。调用 class,检索数据,然后:崩溃!
2015-03-06 09:26:18.978 PostItHours[9174:792018] -[PostItHours.ProjectsViewController didReceiceResponseFromGetClientsRequest:]: 无法识别 select 或发送到实例 0x7fe0c4132c30
2015-03-06 09:26:18.980 PostItHours[9174:792018] 由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序,原因:'-[PostItHours.ProjectsViewController didReceiceResponseFromGetClientsRequest:]:无法识别 select或发送到实例 0x7fe0c4132c30'
如你们所见,它正在尝试在项目ViewController 上执行此操作,该项目已被后退按钮关闭。
有什么想法吗?
我试过了,它对我有用。 2 个视图控制器,每个都有不同的数据源,两者之间有一个 "toSecondVC" segue。
ViewController :
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
}
}
我有一个带有 TableViewController 链的应用程序,由通知控制器链接,从网络服务检索信息。来自下一个 table 的数据是从网络服务中提取的,与前一个选择的数据有关。当我拉动任何 table 进行刷新时,它会再次请求信息,协议会向 table 视图发送委托消息以刷新信息。
嗯,到目前为止一切顺利。但是,我遇到了一些奇怪的事情...示例:我在 tableView #2 上,然后使用导航后退按钮转到上一个 table,即 #1。当在 #1 上,我拉动 table 视图进行刷新时,它崩溃并给我其中一个 "unrecognized selector sent to instance" 告诉我 Tableview #2 没有可选的委托方法,用于获取信息以填充 TableView #1。而且我什至不再使用 TableView #2,iOS 正在将委托消息发送到错误的 ViewController,因为 tableViewController 不是'单击 NavigationController backButton 时甚至被关闭...
有人体验过吗?我知道这看起来有点混乱,但这就是正在发生的事情。
让我们在这里获取一些代码: 两个 TableViewController:客户ViewController 和项目ViewController 当您 select ClientsViewController Table 上的客户端时,它会从 ProjectsViewController Table.
上的客户端加载所有项目客户ViewController
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()' 从网络服务中检索所有客户端并使用委托 'didReceiceResponseFromGetClientsRequest' 重新加载 table。
当客户端被 selected 时,它会转到下一个 TableViewController,在 ViewController 之间传递一个 client_id。
这是项目中的代码示例ViewController
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()
}
它以与客户端相同的方式在屏幕上加载项目,但现在使用委托 'didReceiceResponseFromGetProjectsRequest'
现在,如果我按下导航控制器后退按钮,它会将 ClientsViewController 带回到前面(无需重新加载)...当我拉动它进行刷新时。调用 class,检索数据,然后:崩溃!
2015-03-06 09:26:18.978 PostItHours[9174:792018] -[PostItHours.ProjectsViewController didReceiceResponseFromGetClientsRequest:]: 无法识别 select 或发送到实例 0x7fe0c4132c30 2015-03-06 09:26:18.980 PostItHours[9174:792018] 由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序,原因:'-[PostItHours.ProjectsViewController didReceiceResponseFromGetClientsRequest:]:无法识别 select或发送到实例 0x7fe0c4132c30'
如你们所见,它正在尝试在项目ViewController 上执行此操作,该项目已被后退按钮关闭。
有什么想法吗?
我试过了,它对我有用。 2 个视图控制器,每个都有不同的数据源,两者之间有一个 "toSecondVC" segue。
ViewController :
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
}
}