函数 swift 后值变为空
value becomes null after function swift
我已经练习了几天 swift,只是在调用函数 getItunesData()
后模型 var songItems: [SongItem] = []
变为 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() 函数 returns。 Alamofire.request()
调用触发的网络调用还没有发生,你的关闭代码还没有执行。
#4,接下来执行viewDidLoad()中的行。您的整个 viewDidLoad()
函数完成并且 returns。来自您的Alamofire.request()
(及其完成处理程序)的网络调用仍然没有发生。
系统现在调用你的 tableView.numberOfRowsInSection(_:)
函数,在你将新的歌曲项目安装到 songItems 之前,所以 songItems.count == 0。UIKit 认为你的 table 视图是空的,并将其显示为空。
在将来的某个时间,可能是几秒钟后,您的 Alamofire.request()
触发的网络调用完成,Alamofire 调用您传递给它的闭包。 现在您在#5 处的关闭代码执行。假设网络调用成功,您将结果安装到 self.songItems
正如 Sh_Khan 指出的那样,您应该在完成处理程序中调用 tableView.reloadData()
(上面代码中的#6)
如果不在您的完成处理程序中添加对 tableView.reloadData()
的调用,您永远不会告诉 table 视图现在有数据要显示,而且它看起来是空的。
编辑:
想想这样的异步调用:
您正在做晚饭,发现您需要面包屑。你让你的孩子去商店买。他们前往商店。您不会在让您的孩子拿到面包屑后立即伸手去拿 not-yet-acquired 面包屑。
您继续执行其他任务并等待它们 return。 kid 运行 差事是异步任务。来自您孩子的“这是您的面包屑”是完成处理程序触发。在完成处理程序中,您返回并完成需要面包屑的那部分食谱。
上面代码中的#2(对 Alamofire.request 的调用)是你让你的孩子捡起一些面包屑。
#3 是否将需要 bread-crumbs 的烹饪步骤搁置一旁,继续做其他事情。
#6(完成处理程序中的代码)是当您的孩子回来并说“这是您要的面包屑”时。在 #6 中,您获取面包屑并使用它们完成您等待的那一步。
我已经练习了几天 swift,只是在调用函数 getItunesData()
后模型 var songItems: [SongItem] = []
变为 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() 函数 returns。 Alamofire.request()
调用触发的网络调用还没有发生,你的关闭代码还没有执行。
#4,接下来执行viewDidLoad()中的行。您的整个 viewDidLoad()
函数完成并且 returns。来自您的Alamofire.request()
(及其完成处理程序)的网络调用仍然没有发生。
系统现在调用你的 tableView.numberOfRowsInSection(_:)
函数,在你将新的歌曲项目安装到 songItems 之前,所以 songItems.count == 0。UIKit 认为你的 table 视图是空的,并将其显示为空。
在将来的某个时间,可能是几秒钟后,您的 Alamofire.request()
触发的网络调用完成,Alamofire 调用您传递给它的闭包。 现在您在#5 处的关闭代码执行。假设网络调用成功,您将结果安装到 self.songItems
正如 Sh_Khan 指出的那样,您应该在完成处理程序中调用 tableView.reloadData()
(上面代码中的#6)
如果不在您的完成处理程序中添加对 tableView.reloadData()
的调用,您永远不会告诉 table 视图现在有数据要显示,而且它看起来是空的。
编辑:
想想这样的异步调用:
您正在做晚饭,发现您需要面包屑。你让你的孩子去商店买。他们前往商店。您不会在让您的孩子拿到面包屑后立即伸手去拿 not-yet-acquired 面包屑。
您继续执行其他任务并等待它们 return。 kid 运行 差事是异步任务。来自您孩子的“这是您的面包屑”是完成处理程序触发。在完成处理程序中,您返回并完成需要面包屑的那部分食谱。
上面代码中的#2(对 Alamofire.request 的调用)是你让你的孩子捡起一些面包屑。
#3 是否将需要 bread-crumbs 的烹饪步骤搁置一旁,继续做其他事情。
#6(完成处理程序中的代码)是当您的孩子回来并说“这是您要的面包屑”时。在 #6 中,您获取面包屑并使用它们完成您等待的那一步。