CollectionView에서 여러 항목 선택

13256 단어 SwiftUICollectionView

처음에



이 기사에서는 UICollectionView에서 여러 항목을 선택하는 방법을 소개합니다!

전체 소스 코드는 여기입니다 🔨
htps : // 기주 b. 코 m / h 타로 / 코 c 치온 ゔ ぃ

완성형은 이쪽입니다✌️


환경


Xcode 12.5.1Swift 5.4.2macOS Big Sur 11.5.2

구현 방법



거친 구현 방법은 다음과 같습니다!
1. UICollectionView 에서 복수 선택 가능하도록 설정하기
2. 선택한 항목을 저장할 배열을 준비합니다. (이번 구현의 경우 selectedNumbers)
3. 아이템이 탭되었을 때 selectedNumbers 에 추가
4. 선택한 항목이 다시 탭되면 selectedNumbers 에서 삭제

해당 부분의 코드는 여기입니다! 🚀

ViewController.swift

import UIKit

class ViewController: UIViewController {
  ...
  override func viewDidLoad() {
    super.viewDidLoad()

    ...

    // CollectionViewで複数選択できるように設定する
    collectionView.allowsMultipleSelection = true
  }
}

// MARK:- UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return numbers.count
  }

  // cell初期化時に選択されているか評価する。
  // 選択されている場合は、ハイライトする。そうでない場合は、デフォルトのスタイルを当てる。
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
    let number = numbers[indexPath.row]
    cell.setupLabel(text: String(number))
    if isSelected(number: number) {
      cell.changeBorder()
    } else {
      cell.initBorder()
    }
    return cell
  }
}

// MARK:- UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
  // 選択された時にselectedNumbersにアイテムを追加する
  // 選択された時のスタイルを当てる
  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard
      let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell
    else { return }
    addSelectedNumber(number: numbers[indexPath.row])
    DispatchQueue.main.async {
      cell.changeBorder()
    }
  }

  // 選択解除時された時にselectedNumbersからアイテムを削除する
  // スタイルを元に戻す
  func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    guard
      let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell
    else { return }
    removeSelectedNumber(number: numbers[indexPath.row])
    DispatchQueue.main.async {
      cell.initBorder()
    }
  }
}

extension ViewController {
  ...

  private func addSelectedNumber(number: Int) {
    selectedNumbers.append(number)
  }

  private func removeSelectedNumber(number: Int) {
    selectedNumbers = selectedNumbers.filter({ selectedNumber in
      return selectedNumber != number
    })
  }

  private func isSelected(number: Int) -> Bool {
    return selectedNumbers.contains(number)
  }
}

주의점



선택 상황의 제어에 주의점이 있습니다.CollectionView 에서는 셀이 재사용됩니다.
따라서 스크롤 할 때 선택 상황까지 재사용됩니다.
잘 모르는 상태가 되어 버립니다.
그래서 이번 구현에서는 셀이 초기화될 때마다 선택 상황을 평가하고,
결과에 따라 스타일을 변경했습니다!

ViewController.swift
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
  let number = numbers[indexPath.row]

  // 選択されているなら、ハイライト。そうでないなら、デフォルトのスタイルを当てる。
  cell.setupLabel(text: String(number))
  if isSelected(number: number) {
    cell.changeBorder()
  } else {
    cell.initBorder()
  }
  return cell
}

마지막으로



이번과 같은 CollectionView 에서 복수 아이템을 선택하고 싶을 때는 상당히 있다고 생각합니다.
그러나, 실제로 실장해 보면 생각대로 되지 않는 개소가 많이 있었습니다.
특히 셀이 재사용될 때 선택 상황까지 재사용되는 부분은 확실히 컸다.
참고해 주시면 기쁩니다! 🙏

좋은 웹페이지 즐겨찾기