Перезагрузить CollectionView с разными ячейками - PullRequest
0 голосов
/ 26 марта 2020

Я новичок в Swift и хочу создавать свои первые приложения. В приложении я использую collectionViews, потому что я следую совету Построим это приложение на Youtube.
В моем приложении я хочу иметь вертикальный collectionView. В этом collectionView я хочу другой collectionView, который состоит из 2 разных ячеек: 1x TitleCell и? X ContentCell.
Для этих ячеек отправляется API-запрос для установки их значений. После завершения API-вызова я перезагружаю collectionView с помощью:

  self.collectionView.reloadData()  

К сожалению, когда я перезагружаю данные, мой TitleCell перезаписывается ContentCell. Как я прочитал в быстрых документах о reloadData (): при его вызове он стирает каждую ячейку и заменяет ее последней вызванной ячейкой: в моем случае ContentCell.

Поэтому мой вопрос заключается в том, есть ли способ перезагрузить TitleCell и ContentCell таким образом, чтобы они не перезаписывались?
А также: это плохая практика - создавать collectionView с двумя разными клетки?

Вот мой код:

API:

class ApiService: NSObject {
 static let sharedInstance = ApiService()

 var contentBaseUrl = "netAddress"

  func fetchContent(from url: String, completion: @escaping ([ContentModel]) -> ()) {
    fetchFeedForUrlString(urlString: "\(contentBaseUrl)/"folder"/\(url)", completion: completion)
 }

 func fetchFeedForUrlString<T: Decodable>(urlString: String, completion: @escaping (T) -> ()) {
    let url = URL(string: urlString)
    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in

        guard let data = data else {
            return
        }

        do {
            let json = try JSONDecoder().decode(T.self, from: data)

            DispatchQueue.main.async {
                completion(json)
            }

        } catch let jsonError {
            print(jsonError)
        }

    }

    task.resume()
 }
}

CollectionView, который вызывает API:

class VHomeCell: BaseCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

var firstCell = true
var content: [ContentModel]?

override func setupViews() {
    super.setupViews()

    fetchVideos()
    collectionView.register(HomeContentCell.self, forCellWithReuseIdentifier: "ContentCellID")
    collectionView.register(LeagueCell.self, forCellWithReuseIdentifier: "TitleCellID")
}

//Method that causes the "error"
func fetchMatches() {

    ApiService.sharedInstance.fetchData(from: "ApiNetworkAddress", completion: { (content: [ContentModel]) in
        self.content = content
        self.collectionView.reloadData()
    })
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return content?.count ?? 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if firstCell {
        firstCell = false
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TitleCellID", for: indexPath) as! TitleCell
        return cell
    } else {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ContentCellID", for: indexPath) as! ContentCell
        cell.match = matches?[indexPath.item]
        return cell
    }
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: frame.width, height: 50)
}

ContentCell и TitleCell - это всего лишь 2 UICollectionView Cells с различным содержанием в них:

 class TitleCell: BaseCell {
   var content: ContentModel? {
      didSet {
        title.text = content.titleText
     }
  }
 }

 class ContentCell: BaseCell {
   var content: ContentModel? {
      didSet {
         content.Text = content.text
     }
  }
 }

Вот используемый BaseCell:

class BaseCell: UICollectionViewCell {
  override init(frame: CGRect) {
    super.init(frame: frame)
    setupViews()
  }

func setupViews() {

}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

Я знаю, что мой код нуждается в большой очистке и прочем. Поэтому я рад, если кто-то также может указать, как я могу очистить свой код или сделать его более эффективным.

1 Ответ

0 голосов
/ 26 марта 2020

Вы не должны использовать это свойство firstCell, чтобы определить, какую ячейку настроить в вашем методе cellForItemAt. Вместо этого вы должны использовать параметр indexPath, который передается в метод, чтобы определить, вызывается ли метод для первой ячейки или нет. Вы можете сделать это, проверив indexPath item (вы можете игнорировать indexPath section, поскольку кажется, что у вас есть только один раздел в представлении коллекции).

Итак, удалить свойство firstCell в целом. Затем просто замените это if условие:

if firstCell {

на:

if indexPath.item == 0 {

Чтобы ответить на другой вопрос: нет, это неплохая практика - иметь более одного типа клеток на представление коллекции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...