Swift - ReloadData 未更新
Swift - ReloadData not update
我正在尝试用 Json 结构中的数据填充 Swift 中的 CollectionView,但我无法重新加载数组并解析到 collectionView
我正在声明一个 Array(V_textoturismo) 并将 JSON 的内容解析到它,但似乎无法或者当它通过时我无法重新加载集合视图。
如果我用 static Array(texto) 做它,我做不到没有问题
谢谢 4 一切
我附上我的代码:
import UIKit
struct category: Codable {
let textoturismo: String
let imagenturismo: String
let destinoturismo: String
}
struct Entry_category: Codable {
let categories: [String: category]
}
class CollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet var menuButton:UIBarButtonItem!
var v_textoturismo:[String] = []
var v_imagenturismo:[String] = []
var v_destinoturismo:[String] = []
let imagen = ["Perdidos", "Friends", "Breaking Bad", "Dexter"]
let texto = [NSLocalizedString("Hotels", comment: ""),
NSLocalizedString("Restaurants", comment: ""),
NSLocalizedString("Bars&Pubs", comment: ""),
NSLocalizedString("Discoteques", comment: "")]
override func viewDidLoad() {
super.viewDidLoad()
//collectionView?.dataSource = self;
//collectionView?.delegate = self;
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout{
//layout.minimumLineSpacing = 10
//layout.minimumInteritemSpacing = 10
//layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 0)
//let size = CGSize(width:(collectionView!.bounds.width)/2, height: 150)
let size = CGSize(width:(collectionView!.frame.size.width)/2, height: 150)
layout.itemSize = size
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return v_textoturismo.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let identifier = "Item"
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! SeriesCollectionViewCell
//cell.itemLabel.text = texto[indexPath.row]
cell.itemLabel.text = v_textoturismo[indexPath.row]
cell.itemImage.image = UIImage.init(imageLiteralResourceName: imagen[indexPath.row])
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let item = sender as? UICollectionViewCell
let indexPath = collectionView.indexPath(for: item!)
let detailVC = segue.destination as! DetailViewController
detailVC.detailName = imagen[(indexPath?.row)!]
}
func parseCategories(){
//Leo JSON categorias
NSLog("entro")
if let url2 = URL(string: "http://s369243288.mialojamiento.es/WS_CB_Addicts/categorias_turismo/json_data.php") {
URLSession.shared.dataTask(with: url2) { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
do {
let parsedJSON = try jsonDecoder.decode(Entry_category.self, from: data)
for category in parsedJSON.categories {
self.v_textoturismo.append(category.value.textoturismo)
print(category.value.textoturismo)
self.v_imagenturismo.append(category.value.imagenturismo)
self.v_destinoturismo.append(category.value.destinoturismo)
print(category.value.destinoturismo)
//print(image.value.destino)
}
} catch {
print(error)
}
}
}.resume()
}
//End Leo JSON categorias
}
override func viewWillAppear(_ animated: Bool) {
//super.viewWillAppear(animated)
parseCategories()
//self.collectionView.reloadData()
DispatchQueue.main.async {
self.collectionView.reloadData()
}
print(v_textoturismo)
}
}
您的 collection 视图数据源行被注释掉了,所以我假设您是在 Interface Builder / Storyboards 中设置它?
//collectionView?.dataSource = self;
//collectionView?.delegate = self;
如果未设置这些,您的 collection 视图将始终为空。
旁注:此处不需要分号
接下来,查看您的 viewWillAppear
方法,这里有多个问题。首先,总是总是总是调用 super
除非框架明确告诉你不要这样做。在 iOS 的未来版本中,此处可能存在您可能会错过的隐藏行为。
事实上,docs state:
If you override this method, you must call super at some point in your implementation.
接下来,您可能会考虑只在 viewDidLoad
中调用 parseCategories
而不是 viewWillAppear
。您可能不希望他们每次到达此屏幕时都调用它,例如,如果他们切换标签页。
您的 DispatchQueue.main.async
电话在这里是不必要的。此方法始终在主队列上调用。
这里调用reloadData
也不对,你想在有新数据加载的时候调用,而此时你刚刚调用了parseCategories
发出了网络请求,所以你得等它先回来。
在您的 parseCategories
方法中,您没有处理网络请求返回 Error
或 non-successful HTTP 状态代码的情况。
最后,在解析数据后的成功块中,您将类别添加到数组中,但您从未告诉 collection 视图在此处重新加载。您需要:
DispatchQueue.main.async {
self.collectionView.reloadData()
}
在 将数据添加到 v_textoturismo
数组后。
我正在尝试用 Json 结构中的数据填充 Swift 中的 CollectionView,但我无法重新加载数组并解析到 collectionView 我正在声明一个 Array(V_textoturismo) 并将 JSON 的内容解析到它,但似乎无法或者当它通过时我无法重新加载集合视图。 如果我用 static Array(texto) 做它,我做不到没有问题 谢谢 4 一切 我附上我的代码:
import UIKit
struct category: Codable {
let textoturismo: String
let imagenturismo: String
let destinoturismo: String
}
struct Entry_category: Codable {
let categories: [String: category]
}
class CollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet var menuButton:UIBarButtonItem!
var v_textoturismo:[String] = []
var v_imagenturismo:[String] = []
var v_destinoturismo:[String] = []
let imagen = ["Perdidos", "Friends", "Breaking Bad", "Dexter"]
let texto = [NSLocalizedString("Hotels", comment: ""),
NSLocalizedString("Restaurants", comment: ""),
NSLocalizedString("Bars&Pubs", comment: ""),
NSLocalizedString("Discoteques", comment: "")]
override func viewDidLoad() {
super.viewDidLoad()
//collectionView?.dataSource = self;
//collectionView?.delegate = self;
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout{
//layout.minimumLineSpacing = 10
//layout.minimumInteritemSpacing = 10
//layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 0)
//let size = CGSize(width:(collectionView!.bounds.width)/2, height: 150)
let size = CGSize(width:(collectionView!.frame.size.width)/2, height: 150)
layout.itemSize = size
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return v_textoturismo.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let identifier = "Item"
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! SeriesCollectionViewCell
//cell.itemLabel.text = texto[indexPath.row]
cell.itemLabel.text = v_textoturismo[indexPath.row]
cell.itemImage.image = UIImage.init(imageLiteralResourceName: imagen[indexPath.row])
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let item = sender as? UICollectionViewCell
let indexPath = collectionView.indexPath(for: item!)
let detailVC = segue.destination as! DetailViewController
detailVC.detailName = imagen[(indexPath?.row)!]
}
func parseCategories(){
//Leo JSON categorias
NSLog("entro")
if let url2 = URL(string: "http://s369243288.mialojamiento.es/WS_CB_Addicts/categorias_turismo/json_data.php") {
URLSession.shared.dataTask(with: url2) { data, response, error in
if let data = data {
let jsonDecoder = JSONDecoder()
do {
let parsedJSON = try jsonDecoder.decode(Entry_category.self, from: data)
for category in parsedJSON.categories {
self.v_textoturismo.append(category.value.textoturismo)
print(category.value.textoturismo)
self.v_imagenturismo.append(category.value.imagenturismo)
self.v_destinoturismo.append(category.value.destinoturismo)
print(category.value.destinoturismo)
//print(image.value.destino)
}
} catch {
print(error)
}
}
}.resume()
}
//End Leo JSON categorias
}
override func viewWillAppear(_ animated: Bool) {
//super.viewWillAppear(animated)
parseCategories()
//self.collectionView.reloadData()
DispatchQueue.main.async {
self.collectionView.reloadData()
}
print(v_textoturismo)
}
}
您的 collection 视图数据源行被注释掉了,所以我假设您是在 Interface Builder / Storyboards 中设置它?
//collectionView?.dataSource = self;
//collectionView?.delegate = self;
如果未设置这些,您的 collection 视图将始终为空。
旁注:此处不需要分号
接下来,查看您的 viewWillAppear
方法,这里有多个问题。首先,总是总是总是调用 super
除非框架明确告诉你不要这样做。在 iOS 的未来版本中,此处可能存在您可能会错过的隐藏行为。
事实上,docs state:
If you override this method, you must call super at some point in your implementation.
接下来,您可能会考虑只在 viewDidLoad
中调用 parseCategories
而不是 viewWillAppear
。您可能不希望他们每次到达此屏幕时都调用它,例如,如果他们切换标签页。
您的 DispatchQueue.main.async
电话在这里是不必要的。此方法始终在主队列上调用。
这里调用reloadData
也不对,你想在有新数据加载的时候调用,而此时你刚刚调用了parseCategories
发出了网络请求,所以你得等它先回来。
在您的 parseCategories
方法中,您没有处理网络请求返回 Error
或 non-successful HTTP 状态代码的情况。
最后,在解析数据后的成功块中,您将类别添加到数组中,但您从未告诉 collection 视图在此处重新加载。您需要:
DispatchQueue.main.async {
self.collectionView.reloadData()
}
在 将数据添加到 v_textoturismo
数组后。