У меня есть контроллер UICollectionView, в котором есть ячейка, которая содержит пользовательский UICollectionView с макетом потока, который прокручивается по горизонтали.Эта ячейка является ячейкой коллекции, в которой есть ячейка, в которой хранятся элементы коллекции (CarItemCell).
Проблема в том, что все выглядит хорошо, при первой загрузке все хорошо, но когда я начинаю прокручивать и ячейка начинает использовать повторно,элементы ячейки запутываются и меняют строки ячейки.Я пытался поиграть с prepareForReuse (), но безуспешно, чтобы сделать эту работу.
В коллекции есть миниатюра, но изображения загружаются с помощью библиотеки SDWebImages.
Этоиерархия: CarsViewController -> CarsCell (пользовательский макет потока представления uicollectionview) -> CarItemCell
class CarItemCell: BaseCell {
// MARK: - View properties
let thumbnailView = UIImageView(image: UIImage(), contentMode: .scaleAspectFill)
let carLabel = UILabel(font: UIFont.openSansFontOfSize(15), numberOfLines: 2)
let owner = UILabel(font: UIFont.openSansItalicFontOfSize(14), numberOfLines: 2)
var carItem: CarModel.CarItem? {
didSet {
carLabel.text = carItem?.title
owner.text = carItem?.owner
thumbnailView.sd_setImage(with: URL(string: "http://image.url/image.jpg"), placeholderImage: UIImage(named: "processing"))
}
}
// MARK: - Main Init ♻️
override init(frame: CGRect) {
super.init(frame: frame)
setupStackViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
self.thumbnailView.image = UIImage()
self.carLabel.text = ""
self.owner.text = ""
super.prepareForReuse()
}
// MARK: - Functions
func setupStackViews() {
// views code here
}
}
Это ячейка cars:
class CarsCell: BaseCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
// MARK: Variables declaration
let carBadge = UIImageView(image: #imageLiteral(resourceName: "car") , contentMode: .scaleAspectFit)
let carNameView = UILabel(font: UIFont.openSansSemiboldFontOfSize(18))
@objc lazy var moreButton: UIButton = {
let button = UIButton()
button.setImage(UIImage(named: "dots-menu")?.withRenderingMode(.alwaysTemplate), for: .normal)
button.tintColor = .lightGray
button.addTarget(self, action: #selector(handleMore), for: .touchDown)
return button
}()
/// horizontal scroll layout that represents car items
var cellCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .clear
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.contentInsetAdjustmentBehavior = .automatic
return collectionView
}()
// MARK - didSet
var car: CarModel.Car? {
didSet {
carNameView.text = car?.title
}
}
// MARK: - Main Init ♻️
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
setupViews()
}
// MARK: - Functions
func setupViews(){
cellCollectionView.dataSource = self
cellCollectionView.delegate = self
cellCollectionView.register(CarItemCell.self, forCellWithReuseIdentifier: "carItemCellId")
// setup view here - this is setup OK
}
// MARK: - Collection view delegates
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return car?.carItems?.embedded?.carsItems?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "carItemCellId", for: indexPath) as! CarItemCell
cell.carItem = car?.carItems?.embedded?.carsItems?[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.height / 6 * 5, height: collectionView.frame.height / 6 * 5)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 4, left: 16, bottom: 4, right: 16)
}
override func prepareForReuse() {
super.prepareForReuse()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Это класс контроллера:
class CarViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
// MARK: - Variables declaration
var cars: [CarModel.Car]?
/// cells
fileprivate let cellId = "carCellId"
// MARK: - Init - lifecycle ♻️
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .white
collectionView.register(CarCell.self, forCellWithReuseIdentifier: cellId)
fetchCarData()
}
// MARK: - File private functions
fileprivate func fetchCarData() {
if InternetReachability.isConnectedToNetwork() {
self.showProgressDialog(text: Constants.Messages.LOADING)
DispatchQueue.global(qos: .background).async {
CarManager.instance.getCars(pageNumber: 1, pageSize: 10, completionBlock: { (success, error) in
if success != nil {
if self.cars?.count == 0 {
self.dismissProgressDialog()
return
}
DispatchQueue.main.async {
self.cars = success?.embedded?.cars
self.collectionView.performBatchUpdates({
let indexSet = IndexSet(integer: 0)
self.collectionView.reloadSections(indexSet)
}, completion: nil)
self.dismissProgressDialog()
}
} else {
DispatchQueue.main.async {
ERROR_LOG("error = \(String(describing: error?.localizedDescription))")
self.dismissProgressDialog()
self.showAlert(title: Constants.Messages.CAR, msg: Constants.Messages.OPS_ERROR)
return
}
}
})
}
} else {
self.view.makeToast(Constants.Messages.INTERNET_CONNECTION)
}
}
// MARK: - UICollection View delegate methods
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CarCell
cell.car = cars?[indexPath.item]
cell.layoutMargins = UIEdgeInsets.zero
cell.preservesSuperviewLayoutMargins = false
return cell
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cars?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 250)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
DispatchQueue.main.async {
self.collectionView.collectionViewLayout.invalidateLayout()
}
}
init() {
super.init(collectionViewLayout: UICollectionViewFlowLayout())
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}