UICollectionView с горизонтальной задачей uicollectionview - повторное использование ячеек - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть контроллер 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")
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...