gpt4 book ai didi

ios - 不在每个单元格中使用带有 CollectionView 的 UITableView 中的可重用单元格

转载 作者:行者123 更新时间:2023-11-28 12:19:46 25 4
gpt4 key购买 nike

我有一个 UITableView 并且在它的原型(prototype)单元格中有一个 UICollectionView

MainViewControllerUITableView 的委托(delegate),并且MyTableViewCell 类是 UICollectionView 的委托(delegate)。

在更新每个 TableViewCell 内容时,我调用 cell.reloadData() 使单元格内的 collectionView 重新加载其内容。

当我使用可重复使用的单元格时,每个单元格出现时,最后一个单元格的内容消失了!。然后它从 URL 加载正确的内容。

我最多有 5 到 10 个 UITableViewCells。所以我决定不对 UITableView 使用可重用的单元格。我将 tableView 方法中的单元格创建行更改为:

let cell = MyTableViewCell(style: .default, reuseIdentifier:nil)

然后我在这个函数中的 MyTableViewCell 类(它是 UICollectionView 的委托(delegate))中遇到错误:

override func layoutSubviews() {
myCollectionView.dataSource = self
}

EXC_BAD_INSTRUCTION CODE(code=EXC_I386_INVOP, subcode=0x0)
fatal error: unexpectedly found nil while unwrapping an Optional value

MyTableViewCell.swift

import UIKit
import Kingfisher
import Alamofire

class MyTableViewCell: UITableViewCell, UICollectionViewDataSource {


struct const {
struct api_url {
static let category_index = "http://example.com/api/get_category_index/";
static let category_posts = "http://example.com/api/get_category_posts/?category_id=";
}
}

@IBOutlet weak var categoryCollectionView: UICollectionView!

var category : IKCategory?
var posts : [IKPost] = []

override func awakeFromNib() {
super.awakeFromNib()
// Initialization code

if category != nil {
self.updateData()
}
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

override func layoutSubviews() {
categoryCollectionView.dataSource = self
}

func updateData() {
if let id = category?.id! {
let url = const.api_url.category_posts + "\(id)"
Alamofire.request(url).responseObject { (response: DataResponse<IKPostResponse>) in
if let postResponse = response.result.value {
if let posts = postResponse.posts {
self.posts = posts
self.categoryCollectionView.reloadData()
}
}
}
}
}

internal func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postCell", for: indexPath as IndexPath) as! MyCollectionViewCell

let post = self.posts[indexPath.item]
cell.postThumb.kf.setImage(with: URL(string: post.thumbnail!))
cell.postTitle.text = post.title

return cell
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//You would get something like "model.count" here. It would depend on your data source
return self.posts.count
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}

}

MainViewController.swift

import UIKit
import Alamofire

class MainViewController: UITableViewController {

struct const {
struct api_url {
static let category_index = "http://example.com/api/get_category_index/";
static let category_posts = "http://example.com/api/get_category_posts/?category_id=";
}
}


var categories : [IKCategory] = []

override func viewDidLoad() {
super.viewDidLoad()

self.updateData()
}

func updateData() {
Alamofire.request(const.api_url.category_index).responseObject { (response: DataResponse<IKCategoryResponse>) in
if let categoryResponse = response.result.value {
if let categories = categoryResponse.categories {
self.categories = categories
self.tableView.reloadData()
}
}
}
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
return self.categories.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.categories[section].title
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "CollectionHolderTableViewCell") as! MyTableViewCell
let cell = MyTableViewCell(style: .default, reuseIdentifier:nil)


cell.category = self.categories[indexPath.section]
cell.updateData()

return cell
}

}

MyCollectionViewCell.swift

import UIKit

class MyCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var postThumb: UIImageView!
@IBOutlet weak var postTitle: UILabel!

var category : IKCategory?

}

为什么不重复使用细胞会导致这种情况?为什么我做错了?

最佳答案

有几件事可以帮助您加快速度。

首先,取消注释使用可重用单元格的行并删除创建不可重用单元格的代码行。在这里使用可重复使用的电池是安全的。

其次,在 MyTableViewCell 中,在 super.awakeFromNib() 调用之后立即为 Collection View 设置 dataSource。您只需设置一次 dataSource,但 layoutSubviews() 可能会被多次调用。这不是根据您的需要设置数据源的正确位置。

override func awakeFromNib() {
super.awakeFromNib()
categoryCollectionView.dataSource = self
}

我已经从 awakeFromNib() 中删除了对 updateData() 的调用,因为您已经在创建单元格时调用了它。您也可以删除 layoutSubviews() 覆盖,但作为一般规则,在覆盖它时应小心调用 super.layoutSubviews()

最后,帖子似乎重新出现在错误的单元格中的原因是,当单元格被重复使用时,帖子数组没有被清空。要解决此问题,请将以下方法添加到 MyTableViewCell:

func resetCollectionView {
guard !posts.isEmpty else { return }
posts = []
categoryCollectionView.reloadData()
}

此方法清空数组并重新加载您的 Collection View 。由于现在数组中没有帖子, Collection View 将是空的,直到您再次调用 updateData。最后一步是在单元格的 prepareForReuse 方法中调用该函数。将以下内容添加到 MyTableViewCell:

override func prepareForReuse() {
super.prepareForReuse()
resetCollectionView()
}

让我知道进展如何!

关于ios - 不在每个单元格中使用带有 CollectionView 的 UITableView 中的可重用单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45247616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com