视图控制器返回上一级异常:pop、dismiss与代理传值代码排查
从你给出的代码片段来看,核心问题应该是代理方法sendgetattid(_:_:)没有被正确触发吧?毕竟你在dismiss的闭包里尝试调用代理,但没拿到预期的回调结果。我来帮你梳理几个常见的坑,一步步排查:
1. 代理对象根本没赋值
你定义了var delegate: DataSendDelegate? = nil,但如果在跳转/弹出这个PopController的页面里,没写popController.delegate = self,那闭包里的self.delegate肯定是nil,方法自然不会执行。
解决办法:
在你初始化并展示PopController的代码里,一定要设置代理:
// 比如是present弹出的场景 let popVC = PopController() popVC.delegate = self present(popVC, animated: true) // 如果是push跳转的场景 let popVC = PopController() popVC.delegate = self navigationController?.pushViewController(popVC, animated: true)
同时,那个父页面要遵守协议并实现代理方法:
extension YourParentViewController: DataSendDelegate { func sendgetattid(pop_att_id: Int, pop_in_time: String) { // 这里处理回调过来的数据 print("收到考勤ID:\(pop_att_id),打卡时间:\(pop_in_time)") } }
2. 页面销毁导致代理失效
你同时调用了self.navigationController?.popViewController(animated: true)和self.dismiss(animated: true)——这俩操作是互斥的:如果是push进来的页面,只用pop;如果是present进来的,只用dismiss。同时调用可能导致当前PopController实例提前被释放,闭包里的self变成无效引用,代理调用直接失效。
解决办法:
先判断页面的跳转方式,只执行对应的销毁操作,同时用weak self避免循环引用:
if statuss == "200" { let send_pop_att_id = att_id let send_pop_in_time = in_time // 判断当前页面是push还是present进来的 if let navController = navigationController { navController.popViewController(animated: true) // pop后直接调用代理(因为pop完成后当前VC还没立即销毁) delegate?.sendgetattid(pop_att_id: send_pop_att_id, pop_in_time: send_pop_in_time) } else { // dismiss的话把代理调用放在闭包里,同时用weak self dismiss(animated: true) { [weak self] in guard let self = self else { return } self.delegate?.sendgetattid(pop_att_id: send_pop_att_id, pop_in_time: send_pop_in_time) } } }
3. 代理协议没加class修饰(易忽略的内存问题)
如果你的代理是给ViewController这类类对象用的,一定要给协议加上class修饰,同时把delegate声明为weak,避免循环内存泄漏:
// 给协议加class约束 protocol DataSendDelegate: class { func sendgetattid(pop_att_id: Int, pop_in_time: String) } // delegate用weak修饰 weak var delegate: DataSendDelegate? = nil
这步不仅能避免内存泄漏,还能保证代理对象在被销毁时,delegate会自动变成nil,不会出现野指针问题。
4. 代码截断导致参数传递错误
你的代码最后是send...,看起来没写完,要确保完整调用代理方法时参数传递正确:
self.delegate?.sendgetattid(pop_att_id: send_pop_att_id, pop_in_time: send_pop_in_time)
检查参数名、类型是否和协议定义的完全匹配,别出现拼写错误。
优先从代理赋值和页面销毁这两个点排查,大概率能解决问题~
内容的提问来源于stack exchange,提问作者Sandesh Zote

