我在可调整大小的tablviewCells内部有一个collectionview。 Tableview在每个“ n”个部分中都有一个单元格。数据源和collectionview的委托设置为tableviewCell。在tablview的cellForRowAt上调用了一个API,结果在每个单元的collectionview上呈现。提取结果后,委托将通知tableview加载collectionview,并且应重新加载该单元格,而无需这次调用API。但是问题是我的collectionview数据每隔2个tableviewCells就重复一次。
我知道应该重写prepareForReuse以摆脱单元重用问题。我已经在我的collectionviewCells中实现了prepareForReuse,并将label.text和imageView.image设置为nil。但是我不确定为tableviewCell添加哪些内容来准备prepareForReuse。
// TableView类
override func viewDidLoad() {
super.viewDidLoad()
storiesSections = [....]
tableView.register(UINib(nibName: "RWFeedTableViewCell", bundle: nil), forCellReuseIdentifier: "reuseIdentifier")
tableView.estimatedRowHeight = 1
tableView.rowHeight = UITableView.automaticDimension
}
override func numberOfSections(in tableView: UITableView) -> Int {
return storiesSections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! RWFeedTableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "reuseIdentifier") as! RWFeedTableViewCell
}
cell.delegate = self
cell.fetchData(feedSection: storiesSections[indexPath.section], indexPath: indexPath)
return cell
}
// delegate for tableview reload
func collectionViewDidEnd(updatedFeedSection: FeedSection, indexPath: IndexPath) {
storiesSections[indexPath.section] = updatedFeedSection
tableView.beginUpdates()
tableView.endUpdates()
}
// TableViewCell类
override func awakeFromNib() {
super.awakeFromNib()
initializeCode()
}
func initializeCode() {
// Set layout
self.collectionView.collectionViewLayout = RWWaterfallLayout2()
self.collectionView.register(UINib(nibName: "\(ImageThenTitleViewCell.self)", bundle: nil), forCellWithReuseIdentifier: kImageThenTitleCellID)
self.collectionView.register(UINib(nibName: "\(LeftImageCell.self)", bundle: nil), forCellWithReuseIdentifier: kLeftImageCellID)
self.collectionView.contentInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
self.collectionView.isScrollEnabled = false
self.collectionView.dataSource = self
self.collectionView.delegate = self
}
func fetchData(feedSection: FeedSection, indexPath: IndexPath) {
if feedSection.isLoadComplete {
return
}
if let catID = feedSection.categoryID {
let urlString = URL(string: <urlString>)
let urlRequest = URLRequest(url: urlString!)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: urlRequest) { (data, response, error) in
if error == nil {
} else {
print(error?.localizedDescription as Any)
}
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
guard let todo = try JSONSerialization.jsonObject(with: responseData, options: [])as? [String: Any] else {
print("error trying to convert data to JSON")
return
}
print("success convert data to JSON")
DispatchQueue.main.async {
var updatedFeedSection = feedSection
updatedFeedSection.storiesArray? = (todo["data"]! as! Array)
updatedFeedSection.isLoadComplete = true
self.feedSection = updatedFeedSection
self.collectionView.reloadData()
self.collectionView.performBatchUpdates({
}, completion: { (complete) in
self.collectionViewHeightConstraint.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height + self.collectionView.contentInset.top + self.collectionView.contentInset.bottom
self.delegate?.collectionViewDidEnd(updatedFeedSection: updatedFeedSection, indexPath: indexPath)
})
}
} catch {
print("error trying to convert data to JSON")
return
}
}
task.resume()
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.feedSection == nil {
return 0
} else {
return (self.feedSection?.storiesArray?.count)!
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let indexForTen = indexPath.item%10
let story = self.feedSection?.storiesArray?[indexPath.item]
if indexForTen == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kImageThenTitleCellID, for: indexPath) as! ImageThenTitleViewCell
cell.setupData(story: story!)
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kLeftImageCellID, for: indexPath) as! LeftImageCell
cell.setupData(story: story!)
return cell
}
}
override func prepareForReuse() {
super.prepareForReuse()
}
// Collectionview单元格
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func setupData(story: Dictionary<String, Any>){
self.storyImage.image = nil // reset the image
let thumbImage = story["image"] as! Dictionary<String, String>
self.storyTitle.text = story["t"] as? String
self.storyImage.downloaded(from: (thumbImage["m"])!)
self.layer.borderColor = UIColor.lightGray.cgColor
self.layer.borderWidth = 1
self.layer.cornerRadius = 8
}
override func prepareForReuse() {
super.prepareForReuse()
storyImage.image = nil
storyTitle.text = nil
}
// FeedSection结构
struct FeedSection {
var categoryID: String?
var storiesArray : [Dictionary<String, Any>]?
var isLoadComplete: Bool
init(categoryID: String) {
self.categoryID = categoryID
self.storiesArray = []
self.isLoadComplete = false
}
}
当前第三个tableviewCell重复第一个tablviewCell的数据。如何避免重复单元格数据?
答案 0 :(得分:1)
唯一的问题是TableViewCell
中的feedSection对象。应该在调用fetchData()时对其进行初始化。如果isLoadComplete为true,则只需重新加载collectionView
。
此外,由于isLoadComplete是在URLSession
的完成处理程序上设置的,因此在调用API时将其设置为true。因此,在等待响应时不会调用相同的api。也许可以为FeedSection上的api调用和api响应事件设置一个枚举。但是目前这行得通。
func fetchData(feedSection: FeedSection, indexPath: IndexPath) {
self.feedSection = feedSection
if self.feedSection.isLoadComplete {
self.collectionView.reloadData()
return
}
if let catID = feedSection.categoryID {
let urlString = URL(string: <urlString>)
let urlRequest = URLRequest(url: urlString!)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
self.feedSection.isLoadComplete = true
self.delegate?.collectionViewDidEnd(updatedFeedSection: self.feedSection, indexPath: indexPath)
let task = session.dataTask(with: urlRequest) { (data, response, error) in
if error == nil {
} else {
print(error?.localizedDescription as Any)
}
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
guard let todo = try JSONSerialization.jsonObject(with: responseData, options: [])as? [String: Any] else {
print("error trying to convert data to JSON")
return
}
print("success convert data to JSON")
DispatchQueue.main.async {
self.feedSection.storiesArray? = (todo["data"]! as! Array)
self.feedSection.isLoadComplete = true
self.collectionView.reloadData()
self.collectionView.performBatchUpdates({
}, completion: { (complete) in
self.collectionViewHeightConstraint.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height + self.collectionView.contentInset.top + self.collectionView.contentInset.bottom
self.delegate?.collectionViewDidEnd(updatedFeedSection: self.feedSection, indexPath: indexPath)
})
}
} catch {
print("error trying to convert data to JSON")
return
}
}
task.resume()
}
}
答案 1 :(得分:0)
获取数据后设置UITableView.reloadData()
。
然后检查是否设置了CollectionView.reloadData()
,如果设置为UICollectionView
,请删除 reloadData()。只设置UITableView.reloadData()