Ios 未在UITableView中使用可重用单元格,每个单元格中都包含CollectionView

Ios 未在UITableView中使用可重用单元格,每个单元格中都包含CollectionView,ios,swift,uitableview,uicollectionview,reuseidentifier,Ios,Swift,Uitableview,Uicollectionview,Reuseidentifier,我有一个UITableView,在它的原型单元中有一个UICollectionView MainViewController是UITableView和 MyTableViewCell类是UICollectionView的委托 更新每个TableViewCell内容时,我调用cell.reloadData()以使单元格内的collectionView重新加载其内容 当我使用可重用单元格时,当每个单元格出现时,最后一个单元格的内容都消失了!。然后从URL加载正确的内容 我最多有5到10个UITabl

我有一个
UITableView
,在它的原型单元中有一个
UICollectionView

MainViewController
UITableView
MyTableViewCell
类是
UICollectionView
的委托

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

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

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

let cell = MyTableViewCell(style: .default, reuseIdentifier:nil)
然后,我在MyTableViewCell类(UICollectionView的委托)中得到一个错误,在这个函数中:

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
    }

}
import UIKit

class MyCollectionViewCell: UICollectionViewCell {

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

    var category : IKCategory?

}

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

有几件事可以让你跟上进度

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

其次,在
MyTableViewCell
中,在调用
super.awakeFromNib()
之后设置集合视图的
dataSource
。只需设置一次
数据源
,但
layoutSubviews()
可能会被多次调用。它不是为您的需要设置数据源的正确位置

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

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

func resetCollectionView {
    guard !posts.isEmpty else { return }
    posts = []
    categoryCollectionView.reloadData()
}
此方法清空数组并重新加载集合视图。因为现在数组中没有POST,所以集合视图将为空,直到再次调用updateData。最后一步是在单元格的
prepareforeuse
方法中调用该函数。将以下内容添加到MyTableViewCell:

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

让我知道进展如何

有几件事可以让你跟上进度

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

其次,在
MyTableViewCell
中,在调用
super.awakeFromNib()
之后设置集合视图的
dataSource
。只需设置一次
数据源
,但
layoutSubviews()
可能会被多次调用。它不是为您的需要设置数据源的正确位置

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

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

func resetCollectionView {
    guard !posts.isEmpty else { return }
    posts = []
    categoryCollectionView.reloadData()
}
此方法清空数组并重新加载集合视图。因为现在数组中没有POST,所以集合视图将为空,直到再次调用updateData。最后一步是在单元格的
prepareforeuse
方法中调用该函数。将以下内容添加到MyTableViewCell:

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

让我知道进展如何

使用可重用单元格没有问题,只需在下一个单元格出现之前清除数据源,以防止其显示旧数据。请发布表格单元格的所有代码,这样会更容易解决问题。layoutSubviews()可能不是您要设置dataSource@BJHStudios发布源代码使用可重用单元格没有问题,您只需在下一个单元格出现之前清除数据源,以防止其显示旧数据。请发布表格单元格的所有代码,这样会更容易解决问题。layoutSubviews()可能不是您要设置dataSource@BJHStudios发布了源代码谢谢,一切正常!一个小问题是,当一个新单元格出现时,它是空的,但它会显示另一个单元格的内容一会儿,然后重新加载其正确的内容。你知道发生了什么吗?@Hadu-你可以在重用之前重置单元格,方法是在UITableViewCell/UICollectionViewCell子类中重写
prepareForReuse()
:如果确实重写了它,请确保调用super-请参阅上面链接中的讨论。已编辑以将调用移动到prepareForReuse(),尽管需要注意的是,苹果公司在文档中明确声明,不使用prepareForReuse进行单元格内容调整。然而,如果它在cellForRowAt中不能正常工作,那么我认为把它放在PrepareforUse中并没有什么问题。谢谢,一切都按预期工作!一个小问题是,当一个新单元格出现时,它是空的,但它会显示另一个单元格的内容一会儿,然后重新加载其正确的内容。你知道发生了什么吗?@Hadu-你可以在重用之前重置单元格,方法是在UITableViewCell/UICollectionViewCell子类中重写
prepareForReuse()
:如果确实重写了它,请确保调用super-请参阅上面链接中的讨论。已编辑以将调用移动到prepareForReuse(),尽管需要注意的是,苹果公司在