如何解决函数 swift
我已经练习 swift 几天了,只是在调用函数 getItunesData()
后模型 var songItems: [SongItem] = []
变为 nil 时遇到了这个问题。
我在调用函数中尝试了断点,我仍然可以看到数据,但是之后它变成了 nil。
希望你们能帮我解决这个问题。干杯
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var songItems: [SongItem] = []
let city = ["one","two","three"]
let params = ["term":"marroon5","limit":"5"]
let url: String = "https://itunes.apple.com/search?"
override func viewDidLoad() {
super.viewDidLoad()
getItunesData()
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: "customCell",bundle: nil),forCellReuseIdentifier: "customCell")
}
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
return songItems.count
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell",for: indexPath) as! customCell
cell.labelTxt.text = songItems[indexPath.row].releaseDate
return cell
}
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
}
func getItunesData() {
Alamofire.request(url,method: .get,parameters: params).responseJSON { response in
if response.result.isSuccess {
let json = JSON(response.result.value)
self.songItems = AllSongsModel(json: json).allSongsArray
} else {
}}
}
}
解决方法
我认为您对异步代码的工作方式感到困惑。这段代码:
override func viewDidLoad() {
super.viewDidLoad()
//#1
getItunesData()
//#4
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: "customCell",bundle: nil),forCellReuseIdentifier: "customCell")
}
func getItunesData() {
//#2
Alamofire.request(url,method: .get,parameters: params).responseJSON
//-----------------------------------------
//The code in the braces below does not execute until later.
{ response in
//#5
if response.result.isSuccess {
let json = JSON(response.result.value)
self.songItems = AllSongsModel(json: json).allSongsArray
//#6: Add a call to reloadData() here,once the data is ready.
tableView.reloadData()
} else {
}
}
//-----------------------------------------
//#3
}
执行如下:
#1,您在 viewDidLoad 中,即将调用 getItunesData()
。
#2,在 getItunesData()
内部调用 Alamofire.request()
,传入一个完成处理程序,请求函数将其保存起来以便在请求完成后稍后调用。我用 //----------
破折号括起来的大括号中的代码已保存以备后用,并且不会立即执行。
接下来,执行转到#3。 (Alamofire.request()
调用之后的代码。)那里没有代码,所以 getItunesData() 函数返回。 Alamofire.request()
调用触发的网络调用仍未发生,您的关闭代码仍未执行。
#4,viewDidLoad() 中的行接下来执行。您的整个 viewDidLoad()
函数完成并返回。来自您的 Alamofire.request()
(及其完成处理程序)的网络调用仍然尚未发生。
系统现在调用您的 tableView.numberOfRowsInSection(_:)
函数,在您将新歌曲项安装到 songItems 之前,因此 songItems.count == 0。UIKit 认为您的 table view 为空,并将其显示为空。>
在未来的某个时间,可能是几秒钟后,网络调用您的 Alamofire.request()
触发完成,并且 Alamofire 调用您传递给它的闭包。 现在执行 #5 处的关闭代码。假设网络调用成功,您将结果安装到 self.songItems
正如 Sh_Khan 指出的那样,您应该在完成处理程序中调用 tableView.reloadData()
(上面代码中的 #6)
如果没有在完成处理程序中添加对 tableView.reloadData()
的调用,你永远不会告诉表视图现在有数据要显示,它看起来是空的。
编辑:
想想这样的异步调用:
你正在做晚饭,你意识到你需要面包屑。你让你的孩子去商店买。他们向商店走去。当您要求您的孩子获取尚未获得的面包屑时,您不会立即伸手去拿它们。
您继续执行其他任务并等待它们返回。跑腿的孩子是异步任务。你孩子的“这是你的面包屑”是完成处理程序的触发。在完成处理程序中,您返回并完成需要面包屑的食谱部分。
上面代码中的#2(对 Alamofire.request 的调用)是您让您的孩子拿起一些面包屑。
#3 是您将需要面包屑的烹饪步骤放在一边,继续做其他事情。
#6(完成处理程序中的代码)是当你的孩子回来说“这是你要求的面包屑”时。在 #6 中,您获取面包屑并使用它们完成您一直在等待的那一步。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。