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
相关产品推荐
相关产品推荐

