You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

视图控制器返回上一级异常: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:43:46