[ios] 특정 collectionViewCell를 선택한 상태로 cell 생성하기

감자·2020년 9월 17일
1

ios

목록 보기
3/9
post-custom-banner

why?

->
프로젝트를 하던 중 collectinoViewCell을 생성할 때 특정 Cell이 선택되어 있는 상태로 생성하게 할 필요가 있어서 고민하게되었다. (어떤 기능을 구현하려고 하는지 아래 그림은 보면 좀 더 이해가 잘 될 듯...)

위와 같이 개인 프로필 수정 페이지를 들어가면 상단 customTabBar에 첫번째 Cell이 선택되어 있는 상태로 collectionView를 만들어야 할 필요가 있었다.(customTabBar는 collectionView를 이용해서 만들었다.)

how

->
맨 처음에 어떻게 만들까 고민할 때는 didSelectItemAt, didDeselectItemAt를 이용해서 각 cell이 선택되었을 때 실행되는 로직 및 UI의 변경을 작성해준뒤 맨 처음 cell을 만들때 cellForItemAt를 이용해서 첫번째 cell의 isSelected를 건들려주면 되겠다 해서 작업을 했다.(코드는 아래와같이 구성하였다. )

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileTopCustomCollectionViewCell", for: indexPath) as? ProfileTopCustomCollectionViewCell else{
            return UICollectionViewCell()
        }
        
        if indexPath.row == 0 {
            //collectionView.selectItem(at: indexPath, animated: false , scrollPosition: .init())
            cell.isSelected = true
            
        }
        cell.labelToName.text = profileTopTabBarCellNames[indexPath.row]
        return cell
    }
    // 0번 indexPath에서 isSelected값을 true로 주면서 cell을 생성한다.
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard var cell = collectionView.cellForItem(at: indexPath) as? ProfileTopCustomCollectionViewCell else{
            fatalError()
        }
        
        cell.labelToName.textColor = .black
        cell.viewToBottom.backgroundColor = hexStringToUIColor(hex: "#30BDDC")
        
        actionToSelectedCell(indexPath: indexPath)
    }
    //cell이 선택되었을 때 실행되는 로직이다. 
    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        guard var cell = collectionView.cellForItem(at: indexPath) as? ProfileTopCustomCollectionViewCell else{
            fatalError()
        }
        cell.labelToName.textColor = .lightGray
        cell.viewToBottom.backgroundColor = hexStringToUIColor(hex: "#D3F1F8")
    }
        //선택 되었던 cell의 선택이 풀릴 때 실행되는 로직이다.
        (근데 생각 해보니 그냥 didSelectedIndexPath를 실행할 때만으로 충분히 만들수 있을 것 같네...)
    
class ProfileTopCustomCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var viewToBottom: UIView!
    
    @IBOutlet weak var labelToName: UILabel!
    
    override var isSelected: Bool{
        didSet{
            if isSelected{
                labelToName.textColor = .black
                viewToBottom.backgroundColor = hexStringToUIColor(hex: "#30BDDC")
            }
            else{
                labelToName.textColor = .lightGray
                viewToBottom.backgroundColor = hexStringToUIColor(hex: "#D3F1F8")
            }
        }
    }
}
// cell의 isSelected값의 따른 cell의 UI변동사항을 적용해주기 위해서 isSeleted값을 override하고 프로퍼티 옵저버를 달아주었다.

이렇게 구성하고 빌드하니 잘 되는 것 같았는데 아래와 같은 일이 벌어졌다....

이렇게 첫번째 cell이 아닌 다른 cell을 선택하게 되면 2개의 cell 전부 선택되어있는 상황이 벌어지는 것이다.
그래서 생각을 해보니 몇가지 의심 가는게 있어다.

  • collectionView의 multipleSeletino 여부
  • 맨 처을 실행될 때 isSelected값을 true로 주었지만 이것이 cell이 생성될 때 didSelectedIndexPath를 호출하는 것을 아니지 않을까? 라는 고민

그래서 breakPoint를 걸어놓고 확인을 해보니 역시나 isSelected값이 true가 된다고 해서 didSelectedIndexPath가 호출되는 것이 아니였다.

이 결과를 바탕으로 그럼 특정 cell이 만들어질 때 아예 선택을 해버린 상태로 만들어버리면 될 거 같아서 아래와 같이 코드를 구성해서 빌드하니 아에 아무런 cell도 선택되지 않을 상태로 cell이 만들어지는 문제가 발생하였다.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileTopCustomCollectionViewCell", for: indexPath) as? ProfileTopCustomCollectionViewCell else{
            return UICollectionViewCell()
        }
        
        if indexPath.row == 0 {
            collectionView.selectItem(at: indexPath, animated: false , scrollPosition: .init())
            //cell.isSelected = true
            
        }
        cell.labelToName.text = profileTopTabBarCellNames[indexPath.row]
        return cell
    }


근데 이 경우도 생각해보니 특정 cell을 만들어서 collectionView로 return 해주지도 않은 상태에서 collectionView의 특정 cell을 선택한다는게 말이되지 않는다라는 생각을 하게되었다.

그래서 아래와 같이 처음 cell을 만들 때 isSelecte값을 이용해서 선택되어 있는 상태의 UI를 만들고 selectItem을 이용해서 아직은 cell 만들어져 있지는 않지만 isSelected값을 true로 주었기 때문에 특정 cell를 선택할 수 있게 해주니 내가 원하는대로 작동하게 되었다. (근데 이게 내가 생각하는게 맞는지 모르겠다. 좀 더 자세히 알아볼 필요가 있는듯... )

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileTopCustomCollectionViewCell", for: indexPath) as? ProfileTopCustomCollectionViewCell else{
            return UICollectionViewCell()
        }
        
        if indexPath.row == 0 {
            collectionView.selectItem(at: indexPath, animated: false , scrollPosition: .init())
            cell.isSelected = true
            
        }
        cell.labelToName.text = profileTopTabBarCellNames[indexPath.row]
        return cell
    }

finish

  • collectionView.selectItem(at: indexPath, animated: false , scrollPosition: .init())
위 메소드의 정확한 정의 및 실행로직과 isSelected와의 연관관계를 공부해봐야겠다!
post-custom-banner

0개의 댓글