Collectionview в TableviewCell, данные повторяются - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть вид коллекции внутри моего изменяемого размера tablviewCells.Табличное представление имеет одну ячейку в каждом 'n' количестве разделов.Источник данных и делегат collectionview установлены на tableviewCell.В cellForRowAt tablview вызывается API, и результат отображается в виде коллекции для каждой ячейки.После получения результата делегат сообщает табличному представлению, что представление коллекции загружено, и он должен перезагрузить эту ячейку, не вызывая API на этот раз.Но проблема в том, что мои данные в виде коллекции повторяются после каждых 2 tableviewCells.

Я знаю, что prepareForReuse следует переопределить, чтобы избавиться от проблем повторного использования ячеек.Я реализовал prepareForReuse в моем collectionviewCells и установил для моих label.text и imageView.image значение nil.Однако я не уверен, что добавить в prepareForReuse для моего tableviewCell.

// Класс 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()
    }

// CollectionviewCell


    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


struct FeedSection {
    var categoryID: String?
    var storiesArray : [Dictionary<String, Any>]?
    var isLoadComplete: Bool

    init(categoryID: String) {
        self.categoryID =  categoryID
        self.storiesArray = []
        self.isLoadComplete = false
    }
}

В настоящее время 3-й tableviewCell повторяет данные 1-го tablviewCell.Как избежать повторения данных ячейки?

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

Единственной проблемой был объект feedSection в TableViewCell. Он должен быть инициализирован во время вызова fetchData (). И просто перезагрузите collectionView, если isLoadComplete имеет значение true.

Также, поскольку isLoadComplete установлен на обработчике завершения URLSession, я установил его в true при вызове API времени. Так что тот же API не будет вызываться во время ожидания ответа. Может быть, enum мог бы быть установлен для вызова API и событий ответа API на FeedSection. Но пока это работает.

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()
        }
    }
0 голосов
/ 29 апреля 2019

Установите UITableView.reloadData() после получения данных.И проверьте, если вы установили CollectionView.reloadData(), если да, то удалите reloadData () из UICollectionView.Только набор UITableView.reloadData()

...