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

Alamofire请求数据后数组未更新致TableView无显示及崩溃问题

问题分析与修复步骤

1. 单例与实例混用导致数据不共享

你在ViewController里同时创建了networkingProvider实例,又调用了NetworkingProvider.shared.getUser(),这是两个完全独立的NetworkingProvider对象:

  • 调用单例的getUser()后,数据存在单例的users数组里
  • 但你打印的是自己创建的networkingProvider实例的users.count,自然是0

修复方法:统一使用单例,删除ViewController里的var networkingProvider = NetworkingProvider(),所有操作都用NetworkingProvider.shared:

// ViewController的viewDidLoad里修改:
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "myCustomCell")
    
    // 调用单例的getUser,同时传入闭包监听数据加载完成
    NetworkingProvider.shared.getUser { [weak self] in
        DispatchQueue.main.async {
            self?.tableView.reloadData()
        }
    }
}

2. 异步请求后正确刷新TableView

网络请求是异步执行的,不能在viewDidLoad里直接调用reloadData(),必须等请求完成后再刷新,而且UI操作必须在主线程。同时避免NetworkingProvider直接持有ViewController(会导致循环引用和EXC_BAD_ACCESS),改用闭包回调通知ViewController数据更新:

修改NetworkingProvider的getUser方法:

var users: [User] = []

func getUser(completion: @escaping () -> Void) {
    AF.request("https://randomuser.me/api/?results=1", method: .get)
        .validate(statusCode: 200..<300) // 替换你的statusOK,确保是有效的状态码范围
        .responseDecodable(of: UserResult.self) { [weak self] response in
            guard let self = self else { return }
            if let user = response.value?.results {
                self.users = user
                print(user.count) // 这里会输出1
                completion() // 通知ViewController数据加载完成
            } else {
                print(response.error?.errorDescription ?? "No error")
                completion() // 即使出错也回调,避免UI一直等待
            }
        }
}

3. 修正Model解析错误

你的User结构体里address字段定义为String?,但randomuser.me的API返回的地址是嵌套对象(包含street、city、state等),会导致解析失败(当前请求1条数据可能没触发崩溃,但后续会有问题)。修正Model结构:

struct UserResult: Decodable {
    let results: [User]?
}

struct User: Decodable {
    var name: Name?
    var email: String
    var gender: String?
    var location: Location? // 替换原来的address,对应API的location字段
    var phone: String?
}

struct Name: Decodable {
    var first: String?
}

struct Location: Decodable {
    var street: Street?
    var city: String?
    var state: String?
}

struct Street: Decodable {
    var number: Int?
    var name: String?
}

4. 确保TableView数据源正确指向单例的users数组

在ViewController的numberOfRowsInSection和cellForRowAt方法里,要使用单例的users数组:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return NetworkingProvider.shared.users.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "myCustomCell", for: indexPath) as! CustomTableViewCell
    let user = NetworkingProvider.shared.users[indexPath.row]
    cell.textLabel?.text = user.name?.first ?? "Unknown"
    // 其他字段赋值
    return cell
}

5. 解决EXC_BAD_ACCESS错误

之前的错误是因为你可能在NetworkingProvider里直接持有了ViewController的强引用(比如self.viewController),导致循环引用,对象无法释放,访问时出现野指针。改用闭包回调(上面的completion参数),并且在闭包中使用[weak self]避免循环引用,就能解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:58:01