iOS开发疑问:为何需点击两次按钮才能加载显示RuneScape角色数据?
为什么点击两次按钮才会填充数据?
我一眼就看出问题所在啦——这是异步网络请求的执行顺序在搞鬼!
你在按钮点击事件里发起的URLSession.shared.dataTask是异步执行的:它会在后台线程默默去获取网络数据,而主线程不会等它完成,会直接往下跑更新UI的代码:
totalRank.text = "Rank: " + Total.Rank totalLevel.text = "Level: " + Total.Level totalXP.text = "XP: " + Total.Experience
这时候网络请求还没拿到数据,Total里还是初始的空值,所以UI看起来没变化。等你第二次点击按钮时,第一次的网络请求刚好完成,Total已经被赋值了,这时候更新UI就能显示出数据了。
解决方法
把更新UI的代码移到网络请求的completion闭包里,还要记得切回主线程(iOS要求所有UI操作必须在主线程执行)。我还帮你完善了一些错误判断,避免崩溃:
@IBAction func rsnButton(_ sender: Any) { // 先校验输入不为空 guard let inputRSN = getrsn.text?.trimmingCharacters(in: .whitespaces), !inputRSN.isEmpty else { // 这里可以加个提示,比如弹出"请输入RSN"的alert return } rsn = inputRSN.replacingOccurrences(of: " ", with: "%20") rsn = rsn.replacingOccurrences(of: "-", with: "%2D") print(rsn) let jsonUrlString = "http://services.runescape.com/m=hiscore_oldschool/index_lite.ws?player=" + rsn guard let url = URL(string: jsonUrlString) else {return} URLSession.shared.dataTask(with: url) { (data, response, err) in // 处理数据获取失败的情况 guard let data = data else { print("获取数据失败:\(err?.localizedDescription ?? "未知错误")") return } // 处理数据转字符串失败的情况 guard let dataAsString = String(data: data, encoding: .utf8) else { print("数据转字符串失败") return } let result = dataAsString.components(separatedBy: [",","\n"]) // 校验数据格式是否符合预期,避免数组越界崩溃 guard result.count >= 3 else { print("返回的数据格式不正确") return } self.Total = SkillStats(Rank: result[0], Level: result[1], Experience: result[2]) // 打印 stats 到控制台 print("Total Rank: " + self.Total.Rank) print("Total Level: " + self.Total.Level) print("Total Experience: " + self.Total.Experience) // 切回主线程更新UI DispatchQueue.main.async { self.totalRank.text = "Rank: " + self.Total.Rank self.totalLevel.text = "Level: " + self.Total.Level self.totalXP.text = "XP: " + self.Total.Experience } }.resume() }
额外小提示
- 加了输入校验和数据格式校验,能避免很多潜在的崩溃问题
- 用
trimmingCharacters去掉输入的前后空格,处理用户输入更严谨 - 完善了错误打印,方便你调试排查问题
内容的提问来源于stack exchange,提问作者zjgt37
相关产品推荐
相关产品推荐

