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

Swift 4中如何将URLSession请求函数移至网络类并使用完成回调

没问题,我来帮你把这个网络请求逻辑迁移到独立类里,并用completion handler来传递结果。这样你的视图控制器就能专注于UI逻辑,网络层也能更好地复用~


第一步:创建独立的网络管理类

我们先把网络请求逻辑封装到一个NetworkManager类里,用Result类型来统一处理成功/失败的结果,同时移除原本放在网络层的UI代码(网络层不该负责UI逻辑)。

import Foundation

// 先确保你的ArticleStruct遵循Codable协议(必须的,否则JSONDecoder无法解析)
// struct ArticleStruct: Codable {
//     // 这里定义你的结构体属性,比如:
//     // let id: Int
//     // let title: String
//     // let content: String
// }

class NetworkManager {
    // 用单例模式让这个类全局可访问(也可以根据需求用实例化方式)
    static let shared = NetworkManager()
    
    // 私有化初始化方法,确保只能通过单例访问
    private init() {}
    
    /// 发起JSON请求并返回解析后的Article数组
    /// - Parameters:
    ///   - urlString: 请求的URL字符串
    ///   - completion: 请求完成后的回调,传递Result类型的结果
    func getJsons(from urlString: String, completion: @escaping (Result<[ArticleStruct], Error>) -> Void) {
        // 验证URL合法性
        guard let url = URL(string: urlString) else {
            let invalidURLError = NSError(
                domain: "NetworkError",
                code: -1,
                userInfo: [NSLocalizedDescriptionKey: "无效的请求地址"]
            )
            completion(.failure(invalidURLError))
            return
        }
        
        // 发起网络请求
        URLSession.shared.dataTask(with: url) { data, _, error in
            // 处理网络请求错误
            if let error = error {
                completion(.failure(error))
                return
            }
            
            // 处理空数据情况
            guard let responseData = data else {
                let noDataError = NSError(
                    domain: "NetworkError",
                    code: -2,
                    userInfo: [NSLocalizedDescriptionKey: "未获取到服务器返回的数据"]
                )
                completion(.failure(noDataError))
                return
            }
            
            // 解析JSON数据
            do {
                let articles = try JSONDecoder().decode([ArticleStruct].self, from: responseData)
                completion(.success(articles))
            } catch let decodingError {
                completion(.failure(decodingError))
            }
        }.resume()
    }
}

第二步:在MainViewController中调用

在你的主视图控制器(对应你说的MainActivity)的viewDidLoad里调用这个网络方法,处理结果并更新UI:

import UIKit

class MainViewController: UIViewController, UITableViewDataSource {
    @IBOutlet weak var myTableView: UITableView!
    private var myJsonDataMainActivity: [ArticleStruct] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        myTableView.dataSource = self
        fetchPictureData()
    }
    
    private func fetchPictureData() {
        let requestURL = "http://192.168.178.100/getPicture.php"
        NetworkManager.shared.getJsons(from: requestURL) { [weak self] result in
            // 所有UI操作必须回到主线程
            DispatchQueue.main.async {
                switch result {
                case .success(let articles):
                    // 赋值并刷新表格
                    self?.myJsonDataMainActivity = articles
                    self?.myTableView.reloadData()
                    print("成功获取到 \(articles.count) 条图片数据")
                case .failure(let error):
                    // 这里处理错误,比如弹出提示框
                    let alert = UIAlertController(
                        title: "加载失败",
                        message: error.localizedDescription,
                        preferredStyle: .alert
                    )
                    alert.addAction(UIAlertAction(title: "确定", style: .default))
                    self?.present(alert, animated: true)
                }
            }
        }
    }
    
    // MARK: - UITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myJsonDataMainActivity.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "PictureCell", for: indexPath)
        let article = myJsonDataMainActivity[indexPath.row]
        // 配置单元格内容,比如 cell.textLabel?.text = article.title
        return cell
    }
}

第三步:在其他类中调用

其他视图控制器的调用逻辑几乎一致,只是请求URL和数据存储变量不同:

import UIKit

class OtherViewController: UIViewController, UITableViewDataSource {
    @IBOutlet weak var otherTableView: UITableView!
    private var myJsonDataOtherClass: [ArticleStruct] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        otherTableView.dataSource = self
        fetchOtherData()
    }
    
    private func fetchOtherData() {
        let requestURL = "http://192.168.178.100/getData.php"
        NetworkManager.shared.getJsons(from: requestURL) { [weak self] result in
            DispatchQueue.main.async {
                switch result {
                case .success(let articles):
                    self?.myJsonDataOtherClass = articles
                    self?.otherTableView.reloadData()
                case .failure(let error):
                    let alert = UIAlertController(
                        title: "加载失败",
                        message: error.localizedDescription,
                        preferredStyle: .alert
                    )
                    alert.addAction(UIAlertAction(title: "确定", style: .default))
                    self?.present(alert, animated: true)
                }
            }
        }
    }
    
    // MARK: - UITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myJsonDataOtherClass.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DataCell", for: indexPath)
        let article = myJsonDataOtherClass[indexPath.row]
        // 配置单元格内容
        return cell
    }
}

几个关键注意点

  1. 避免循环引用:用[weak self]捕获self,防止闭包持有视图控制器导致内存泄漏
  2. 主线程更新UI:所有UI操作(比如刷新表格、弹出提示框)必须放在DispatchQueue.main.async里执行
  3. 单一职责原则:网络类只负责网络请求和数据解析,UI逻辑交给视图控制器处理,这样代码更清晰、易维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:48:43