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

Swift中如何在另一个函数中访问JSON解析时使用的变量?

问题解决:Swift中API返回值作用域与UI更新问题

错误原因

你遇到的Cannot find 'textData' in scope错误,核心原因是:

  • textData是URLSession闭包内部的局部变量,它的作用域仅限于闭包里的do代码块,configureRandomText方法根本无法访问到这个变量。
  • 更关键的是,你在viewDidLoad里先调用了configureRandomText,这时候API请求还没开始返回数据,就算能访问到textData,它也不存在。

修正方案

调整代码逻辑,移除无效赋值,同时确保UI更新在主线程执行,另外优化数据模型写法:

import UIKit

class RandomVC: UIViewController {
    // 用结构体做解码模型,遵循Swift命名规范(首字母大写)
    struct RandomData: Decodable {
        var text: String
    }
 
    var randomText = UILabel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemBackground
        configureRandomText()
        fetchRandomFact()
    }
    
    // 网络请求抽为单独方法,代码更清晰
    func fetchRandomFact() {
        let jsonUrlString = "https://uselessfacts.jsph.pl/random.json?language=en"
        guard let url = URL(string: jsonUrlString) else { return }
        
        URLSession.shared.dataTask(with: url) { [weak self] (data, response, err) in
            guard let self = self else { return }
            guard let data = data else { 
                print("未获取到数据")
                return 
            }
            
            do {
                let textData = try JSONDecoder().decode(RandomData.self, from: data)
                print(textData.text)
                // 必须在主线程更新UI,URLSession闭包默认运行在后台线程
                DispatchQueue.main.async {
                    self.randomText.text = textData.text
                }
            } catch let jsonErr {
                print("JSON解析错误:" , jsonErr)
            }
        }.resume()
    }
    
    func configureRandomText() {
        view.addSubview(randomText)
        randomText.translatesAutoresizingMaskIntoConstraints = false
        // 设置默认提示文本,移除原来的无效赋值
        randomText.text = "正在加载..."
        randomText.numberOfLines = 0 // 允许文本换行,适配长内容
        randomText.textAlignment = .center
        
        NSLayoutConstraint.activate([
            randomText.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            randomText.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            // 增加左右边距,避免文本贴边
            randomText.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            randomText.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)
        ])
    }
}

关键改动点

  • 将嵌套的randomData类改为RandomData结构体,符合Swift编码习惯。
  • 网络请求抽为单独的fetchRandomFact方法,代码结构更清晰。
  • 使用[weak self]避免循环引用,预防内存泄漏。
  • 用DispatchQueue.main.async包裹UI更新代码,确保在主线程执行(后台线程直接更新UI会导致崩溃)。
  • 移除configureRandomText中无效的textData.text赋值,替换为默认提示文本,同时给UILabel添加换行和边距,优化显示效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:50:45