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

