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

解决结构体/TableView Cell中无法弹窗的问题:JSON解析异常时如何触发弹窗提示

解决结构体/TableView Cell中无法弹窗的问题:JSON解析异常时如何触发弹窗提示

兄弟,你踩的这个坑我之前也遇到过——结构体本身不是UI组件,根本拿不到present方法的上下文,所以直接在里面写弹窗肯定行不通。咱们换个思路,把弹窗的活儿交给管TableView的SearchPoi类来干,结构体只负责解析数据和传递状态就行,具体操作看下面:

第一步:改造结构体的解析方法,通过闭包传递弹窗需求

把原来只负责解析的方法,加一个专门的回调闭包,用来通知外部“需要弹窗”的状态,同时把弹窗需要的标题、消息传出去:

struct SearchApi { // 注意Swift命名规范,结构体首字母大写哦
    static var dataFromSearchApi: [YourResultModel]? // 替换成你的实际结果类型
    
    func newParseJSON(poiData: Data,
                      completionHandler: @escaping () -> Void,
                      alertHandler: @escaping (String, String) -> Void) {
        let decoder = JSONDecoder()
        do {
            let decodedData = try decoder.decode(POIData.self, from: poiData)
            // 检查解析结果是否为空
            guard let validResults = decodedData.results, !validResults.isEmpty else {
                // 结果为空,触发弹窗回调
                alertHandler("Json Empty", "未获取到有效数据,请重试")
                completionHandler()
                return
            }
            SearchApi.dataFromSearchApi = validResults
            completionHandler()
        } catch {
            // 解析失败时也可以触发弹窗,把错误信息传出去
            alertHandler("解析失败", error.localizedDescription)
            print(error)
        }
    }
}

第二步:在SearchPoi类中实现弹窗逻辑

因为SearchPoi是ViewController,拥有present方法的上下文,所以在这里处理弹窗是最合理的。调用结构体的解析方法时,把弹窗的逻辑写在alertHandler里:

class SearchPoi: UIViewController, UITableViewDataSource, UITableViewDelegate {
    // 你的TableView实例、数据源等代码...
    
    // 假设这是你触发数据解析的方法
    func loadAndParsePoiData() {
        // 先获取到要解析的poiData(比如从网络请求或者本地文件读取)
        guard let poiData = getPoiData() else { return }
        
        let searchApi = SearchApi()
        searchApi.newParseJSON(poiData: poiData,
                               completionHandler: { [weak self] in
            // 解析成功后刷新TableView
            self?.tableView.reloadData()
        }, alertHandler: { [weak self] title, message in
            // 这里写弹窗逻辑,因为在ViewController里,所以可以正常调用present
            let dialogMessage = UIAlertController(title: title, message: message, preferredStyle: .alert)
            let okAction = UIAlertAction(title: "OK", style: .default) { _ in
                print("Ok button tapped")
            }
            dialogMessage.addAction(okAction)
            self?.present(dialogMessage, animated: true)
        })
    }
    
    // 模拟获取poiData的方法,根据你的实际情况替换
    private func getPoiData() -> Data? {
        // 你的数据获取逻辑...
        return nil
    }
}

额外提醒

  • 尽量遵循Swift的命名规范,比如结构体、类名首字母大写,方法名小驼峰,这样代码可读性更高。
  • 结构体的职责应该聚焦在数据处理上,UI相关的逻辑(弹窗、页面跳转等)都交给ViewController或者专门的UI管理类,这样代码的职责更清晰,也避免了上下文缺失的问题。
  • 用[weak self]避免循环引用,这是闭包回调里的常规操作,防止内存泄漏。

备注:内容来源于stack exchange,提问作者submariner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 08:34:32