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

Swift开发:iPhone/tvOS应用JSON解析后Label不更新及self疑问

问题解答:JSON解析后Label不显示内容&self的使用原因

嘿,这两个问题都是iOS/tvOS开发里很常见的小坑,我帮你一一拆解:

1. 为什么需要用self.Title_Label?

在Swift的逃逸闭包(比如URLSession.shared.dataTask的闭包——这种会在函数执行完之后才被调用的闭包)中,编译器要求你显式使用self来访问实例属性,原因有两个:

  • 明确指代当前ViewController实例的属性,避免和闭包内部的局部变量重名混淆;
  • 提醒你注意闭包可能捕获self导致的循环引用风险(虽然这里URLSession的闭包不会导致循环引用,但显式写self是规范的做法,如果你担心的话可以用weak self+guard let self = self else { return }来进一步优化)。

如果是在普通的类方法里(比如viewDidLoad),你可以直接写Title_Label,不需要self,但闭包里必须显式声明。

2. Label不显示内容的核心原因(两个关键点)

你的代码没有报错,但Label没内容,是因为两个容易忽略的细节:

① 你从未调用getNewTitles()方法

目前你的getNewTitles()方法只是定义了,但没有在任何地方触发执行!网络请求都没跑,自然不会有数据更新到Label上。
需要在viewDidLoad里加上调用:

override func viewDidLoad() {
    super.viewDidLoad()
    getNewTitles() // 加上这行,触发网络请求
}

② 在后台线程更新UI

URLSession的dataTask闭包是在后台线程执行的,而所有UI操作(比如设置Label的text)必须在主线程进行。你直接在闭包里设置self.Title_Label.text = newsstring,系统不会报错,但UI不会刷新。
需要把更新UI的代码包裹到主线程调度里:

do {
    let todo = try JSONDecoder().decode(ToDo.self, from: data)
    let newsstring = todo.title
    // 切换到主线程更新UI
    DispatchQueue.main.async {
        self.Title_Label.text = newsstring
    }
} catch {
    print(error)
}

修复后的完整代码

import UIKit
class ViewController: UIViewController {
    @IBOutlet weak var Title_Label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getNewTitles() // 触发网络请求
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    @objc func getNewTitles(){
        struct ToDo : Decodable {
            let userId, id : Int
            let title : String
            let completed : Bool
        }
        
        let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")!
        URLSession.shared.dataTask(with:url) { [weak self] data, _, error in // 用weak self避免潜在循环引用
            guard let data = data else { 
                print(error ?? "Unknown error"); 
                return 
            }
            do {
                let todo = try JSONDecoder().decode(ToDo.self, from: data)
                let newsstring = todo.title
                // 切回主线程更新UI
                DispatchQueue.main.async {
                    guard let self = self else { return }
                    self.Title_Label.text = newsstring
                }
            } catch {
                print(error)
            }
        }.resume()
    }
}

这样修改后,你的Label应该就能正常显示JSON里的title内容了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:05:51