使用 UICollectionView 执行 Segue 时出错



当我单击任何UICollectionView项目时,我在PerformSegue行上收到此错误:

线程 1:致命错误:索引超出范围

但是,编译器不读取该函数,只是直接跳转到 PerformSegue,所以我最终退出了索引。我该如何解决这个问题?当用户单击任何 UICollectionView 索引时,我必须替换函数参数中的索引路径并重复该过程。

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
getCategoriaPorID(IdCategoria: indexPath.row) { (data) in
DispatchQueue.main.async {
self.dataCategoriaID = data
}
}
performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID[indexPath.row])
}

完整的视图控制器文件:

import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UITableViewDataSource, UITableViewDelegate, UICollectionViewDelegate {
@IBOutlet weak var tableViewTopSell: UITableView!
@IBOutlet var collectionView: UICollectionView!
@IBOutlet weak var collectionViewBanner: UICollectionView!
var indexPathId = Int()
var dataSource: [Content] = [Content]()
var dataBanner: [Banner] = [Banner]()
var dataTopSold: [Top10] = [Top10]()
var dataCategoriaID: [CategoriaIDItems] = [CategoriaIDItems]()
override func viewDidLoad() {
super.viewDidLoad()
//Delegate TableView
self.tableViewTopSell.delegate = self
//SetupNavBarCustom
self.navigationController?.navigationBar.CustomNavigationBar()
let logo = UIImage(named: "tag.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
//CallAPIData
getTopSold { (data) in
DispatchQueue.main.async {
self.dataTopSold = data
self.tableViewTopSell.reloadData()
}
}
getBanner { (data) in
DispatchQueue.main.async {
self.dataBanner = data
self.collectionViewBanner.reloadData()
}
}
getAudiobooksAPI { (data) in
DispatchQueue.main.async {
self.dataSource = data
self.collectionView.reloadData()
}
}
}
//CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (collectionView == self.collectionView) {
return  self.dataSource.count
}else{
return self.dataBanner.count
}}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if (collectionView == self.collectionView) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell
let content = self.dataSource[indexPath.item]
cell.bookLabel.text = content.descricao
cell.bookImage.setImage(url: content.urlImagem, placeholder: "")
return cell
}else if (collectionView == self.collectionViewBanner) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCellBanner", for: indexPath) as! CollectionViewCell
let content = self.dataBanner[indexPath.item]
cell.bannerImage.setImage(url: content.urlImagem, placeholder: "")

return cell
}
return UICollectionViewCell()
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
getCategoriaPorID(IdCategoria: indexPath.row) { (data) in
DispatchQueue.main.async {
self.dataCategoriaID = data
}
}
performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID[indexPath.row])
}



//TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataTopSold.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "topSoldCell", for: indexPath) as! TableViewCell
let content = self.dataTopSold[indexPath.row]
cell.labelNomeTopSell.text = content.nome
cell.imageViewTopSell.setImage(url: content.urlImagem, placeholder: "")
cell.labelPrecoDe.text = "R$ (content.precoDe)"
//Colocar strike em cima do Preco Antigo
let oldPrice = "R$ (content.precoDe)"
let promotionString = oldPrice + ""
let attributedStr = NSMutableAttributedString(string: promotionString)
let crossAttr = [NSAttributedStringKey.strikethroughStyle: NSUnderlineStyle.styleSingle.rawValue]
attributedStr.addAttributes(crossAttr, range: NSMakeRange(0, oldPrice.count))
cell.labelPrecoDe.attributedText = attributedStr
//
cell.labelPrecoPor.text = "R$ 119.99"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "segueId", sender:self.dataTopSold[indexPath.row])
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueId" {
let des = segue.destination as? TelaDetalheProdutos
//.item possui uma propriedade instanciada na TelaDetalheProdutos
des?.item = (sender as? Top10)
//Segue para CollectionView Categorias
} else if segue.identifier == "segueCategorias" {
let desc = segue.destination as? TelaCategorias
desc?.item = (sender as? CategoriaIDItems)
}
}
}
//Cast UIImage Extension
extension UIImageView{
func setImage(url : String, placeholder: String, callback : (() -> Void)? = nil){
self.image = UIImage(named: "no-photo")
URLSession.shared.dataTask(with: NSURL(string: url)! as URL, completionHandler: { (data, response, error) -> Void in
guard error == nil else{
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
if let callback = callback{
callback()
}
})
}).resume()
}
}

仅使用主线程更新 UI。问题是您正在主线程上设置dataCategoriaID,我假设它在异步网络调用函数中。因此,您正在尝试在设置dataCategoriaID之前执行segue,这就是它为空并抛出错误的原因index out of range

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
getCategoriaPorID(IdCategoria: indexPath.row) { (data) in
self.dataCategoriaID = data
performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID[indexPath.row])
}
}

最新更新