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

Swift中使用WikipediaKit与代理模式的网络请求问题排查

问题分析与解决方案

核心问题

  1. 代理失效原因:你在TopTenViewController中调用的albumManager和AlbumInfoViewController里初始化的albumManager是两个完全独立的实例。发起网络请求时,前者的delegate为nil,而后者设置代理的是另一个实例,所以回调永远不会触发。
  2. 时序问题:网络请求是异步操作,你先调用getAlbumInfo立刻执行performSegue,此时请求还未完成,新视图已经加载,且因为实例不共享,后续结果也无法传递。

修复方案:让新视图负责发起请求(更符合职责划分)

步骤1:修改TopTenViewController,传递专辑标题到新视图

extension TopTenViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        performSegue(withIdentifier: "topTenAlbumInfoSeg", sender: indexPath)
    }
}

// 添加prepare方法传递数据
extension TopTenViewController {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "topTenAlbumInfoSeg",
           let indexPath = sender as? IndexPath,
           let destVC = segue.destination as? AlbumInfoViewController {
            // 把选中的专辑标题传给新视图
            destVC.targetAlbumTitle = topTenList[indexPath.row][1]
        }
    }
}

步骤2:修改AlbumInfoViewController,接收标题并发起请求

class AlbumInfoViewController: UIViewController, AlbumManagerDelegate {
    @IBOutlet weak var albumDescriptionLabel: UILabel!
    @IBOutlet weak var myWebView: WKWebView!
    
    // 添加属性接收专辑标题
    var targetAlbumTitle: String = ""
    var albumManager = AlbumManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        albumManager.delegate = self
        // 拿到标题后发起请求
        albumManager.getAlbumInfo(albumTitle: targetAlbumTitle)
    }

    func didUpdateAlbumInfo(albumInfo: String) {
        DispatchQueue.main.async {
            print("This worked: \(albumInfo)")
            self.albumDescriptionLabel.text = "Hi this is: \(albumInfo)"
        }
    }
}

步骤3:优化AlbumManager避免循环引用

protocol AlbumManagerDelegate: AnyObject { // 限制仅类遵守协议
    func didUpdateAlbumInfo(albumInfo: String)
}

struct AlbumManager {
    weak var delegate: AlbumManagerDelegate? // 用weak避免循环引用

    func getAlbumInfo(albumTitle: String) {
        let wikipedia = Wikipedia.shared
        let language = WikipediaLanguage("en")
        
        let _ = wikipedia.requestArticle(language: language, title: albumTitle, imageWidth: 5) { [weak self] result in
            guard let self = self else { return }
            switch result {
            case .success(let article):
                print(article.displayTitle)
                self.delegate?.didUpdateAlbumInfo(albumInfo: article.displayTitle)
                print("delegate should be updated")
            case .failure(let error):
                print(error)
            }
        }
    }
}

额外优化:用Completion Handler替代代理(更简洁)

如果你觉得代理繁琐,可以用闭包代替,代码更紧凑:
修改AlbumManager的getAlbumInfo方法:

struct AlbumManager {
    func getAlbumInfo(albumTitle: String, completion: @escaping (Result<String, Error>) -> Void) {
        let wikipedia = Wikipedia.shared
        let language = WikipediaLanguage("en")
        
        let _ = wikipedia.requestArticle(language: language, title: albumTitle, imageWidth: 5) { result in
            switch result {
            case .success(let article):
                completion(.success(article.displayTitle))
            case .failure(let error):
                completion(.failure(error))
            }
        }
    }
}

然后AlbumInfoViewController里直接调用:

override func viewDidLoad() {
    super.viewDidLoad()
    albumManager.getAlbumInfo(albumTitle: targetAlbumTitle) { [weak self] result in
        guard let self = self else { return }
        DispatchQueue.main.async {
            switch result {
            case .success(let title):
                self.albumDescriptionLabel.text = "Hi this is: \(title)"
            case .failure(let error):
                print(error)
                self.albumDescriptionLabel.text = "加载失败"
            }
        }
    }
}

这样就不需要代理协议,代码更简洁,也彻底避免了代理实例不匹配的问题。


内容的提问来源于stack exchange,提问作者Jake Jake

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:10:52