apple/UIKit & ReactiveX

UICollectionView isSelected 정리

lgvv 2024. 8. 16. 01:08

UICollectionView isSelected 정리

 

  • UICollectionView에서 overrdie isSelected를 통해 상태를 변경할 수 있음
  • 사용자가 선택할 때마다 isSelected가 변경됨.
    • 주의할 점: isSelected를 override해서 사용하는 경우 버전에 따라 선택 상태가 제대로 UI에 반영되지 않을 수 있음.
    • TableView에서는 동작성이 다름.
    • UITableView 사용성 링크: https://rldd.tistory.com/628
  • 호출순서
    • override isSelected (이전에 선택된 아이템)
    • DeSelect (이전에 선택된 아이템)
    • override isSelected (현재 선택된 아이템)
    • didSelect (현재 선택된 아이템)

동작

예제코드

import UIKit
import SwiftUI
import SnapKit

struct SmapleViewControllerSwiftUIView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        return SmapleViewController()
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        
    }
}

final class SmapleViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        configureUI()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        let items = Array(1...100)
        collectionView.configure(items)
    }
    
    let collectionView = SampleCollectionView()
    
    private func configureUI() {
        view.addSubview(collectionView)
        collectionView.snp.makeConstraints {
            $0.edges.equalToSuperview()
        }
    }
}

final class SampleCollectionView: UICollectionView,
                                  UICollectionViewDelegate,
                                  UICollectionViewDataSource,
                                  UICollectionViewDelegateFlowLayout {
    private var array = [Int]()
    
    func configure(_ items :[Int]) {
        self.array = items
    }
    
    // MARK: - Initialize
    
    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        let layout = UICollectionViewFlowLayout()
        super.init(frame: frame, collectionViewLayout: layout)
        
        self.register(SampleCollectionViewCell.self, forCellWithReuseIdentifier: SampleCollectionViewCell.id)
        
        delegate = self
        dataSource = self
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return array.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: SampleCollectionViewCell.id,
            for: indexPath
        ) as? SampleCollectionViewCell else { return .init() }
        
        let number = array[indexPath.item]
        cell.confiure(number: number)
        
        if indexPath.item == 0 {
            cell.isSelected = true
            self.selectItem(at: indexPath,
                            animated: false,
                            scrollPosition: .top)
        } else {
            cell.isSelected = false
            self.deselectItem(at: indexPath, animated: false)
        }
        
        print(#function)
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let width = (UIScreen.main.bounds.width - 20) / 2
        
        return .init(width: width, height: 100)
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print(#function)
    }
    
    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        print(#function)
    }
}

final class SampleCollectionViewCell: UICollectionViewCell {
    static let id = String(describing: SampleCollectionViewCell.self)
    
    override var isSelected: Bool {
        willSet {
            print("override isSelected 호출")
            self.backgroundColor = newValue
            ? .red
            : .gray
        }
    }
    
    func confiure(number: Int) {
        numberLabel.text = "\(number)"
    }
    
    // MARK: - Initialize
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        configureUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - UIComponents
    
    private lazy var numberLabel: UILabel = {
        $0.font = .systemFont(ofSize: 30, weight: .bold)
        $0.textAlignment = .center
        return $0
    }(UILabel())
    
    private func configureUI() {
        contentView.addSubview(numberLabel)
        numberLabel.snp.makeConstraints {
            $0.edges.equalToSuperview()
        }
    }
}

#Preview {
    SmapleViewController()
}