Swift

iOS Custom Calendar 구현하기 5

Thor_yeom 2023. 4. 20. 20:28

안녕하세요 

기본틀을 만들어졌으니

본격적으로 Custom Calendar를 만들어보겠습니다.

 

혹시 아직도 기본틀을 만들어 놓지 않으신 분들은

아래 블로그를 참고하시면 됩니다.

 

https://yeomir.tistory.com/22

 

iOS Custom Calender 구현하기

Uikit으로 돌아왔습니다. 이번에는 라이브러리를 사용하지 않고 CustomCalendar를 구현해보도록 하겠습니다. 1) 최상단에 있는 View를 먼저 구현해보겠습니다. 최상단은 button, title, button button으로 구성

yeomir.tistory.com

 

 

자 시작! 

 

클릭했을때 Cell의 배경 색을 바꾸게 하려면 어떻게 해야할까?

 

1) UICollectionViewDelegate의 메소드가 무엇이 있는지 찾아본다.

// MARK: - UICollectionViewDataSource
extension CustomCalendarViewController: UICollectionViewDataSource, UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // Cell의 갯수를 보여주기 위해 임의로 값을 설정
        return days.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        // cell 구현
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CustomCalCollectionViewCell.self), for: indexPath) as! CustomCalCollectionViewCell
        // 배열로 만들어진 String들을 dayLabel.text에 하나씩 넣어줍니다.
        cell.dayLabel.text = days[indexPath.item]
        return cell
    }
}

 

기존 코드에 보면 UICollectionViewDelegate가 보입니다.

TableView에서도 터치하거나 글자수를 제한한다거나 할때

UITableViewDelegate을 사용하시는 것과 같습니다.

 

공식문서를 보면

공식 문서 출처
공식 문서 Topics 부분

 

UICollectionViewDelegate을 채택하면 

다양한 메소드를 사용하여 활용할 수있습니다.

 

그 중에서도 didSetlectItemAtdidDeSetlectItemAt

활용하면 쉽게 가능합니다.

 

조금 자세하게 보면

해석을 해보면 "지정된 인덱스 경로의 항목이 선택되었음을 대리자에게 알립니다."

쉽게 설명하면 지정되었으면 대리자에 알린다.

이부분이 포인트 입니다.

 

 

다음으로는

해석을 해보자면 "지정된 경로의 항목이 선택 취소되었음을 대리자에게 알립니다."

앞에 De가 붙었기때문에 직감적으로 반대라고 생각하시면 됩니다.

지정된 것이 취소되었다는 것을 대리자에게 알린다.

 

자. 그렇다면 활용을 해볼까요?

 

2) didSetlectItemAt 과 didDeSetlectItemAt 적용

extension CustomCalendarViewController: UICollectionViewDataSource, UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // Cell의 갯수를 보여주기 위해 임의로 값을 설정
        return days.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        // cell 구현
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CustomCalCollectionViewCell.self), for: indexPath) as! CustomCalCollectionViewCell
        // 배열로 만들어진 String들을 dayLabel.text에 하나씩 넣어줍니다.
        cell.dayLabel.text = days[indexPath.item]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        <#code#>
    }
    
    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        <#code#>
    }
}

 

자 메서드를 추가했습니다. 추가만 한다고 끝날까요?

그러면 얼마나 좋겠어요...ㅠ

 

3) didSelectItemAt 메소드를 채워 줍니다.

 

어떻게 채워줄까... Cell에게 영향을 줘야될거 같은데 

cellForRowAt에 들어가는 것 처럼 해보면 될까...

했는데 전혀 작용을 안했습니다.

 

이것저것 뭔가 있는지 찾아보다가...

유레카!!!

 

cellForItem

이런걸 찾았지말입니다... 

IndexPaht를 매개변수로 받아 Cell을 리턴하네?

 

적용해보자구

 

너무 좋네요!~

2) Cell의 배경색을 바꿔보겠습니다.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath)
        cell?.backgroundColor = .yellow
    }

 

빌드 해봅시다.

 

흠... 뭔가 된거 같으면서도 안된거같으면서도...

자 그러면 이상해보이는 부분이

 

빈곳을 터치해도 배경색이 바뀌는것

하나씩 선택했을때 기존의 배경색이 남아있는 것 입니다.

 

해결해봅시다.

 

4) didDeselectItemAt을 활용

 

여기서 등장합니다.

    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath)
        cell?.backgroundColor = .clear
    }

collectionView.cellForItem의 역할도 알았겠다

배경 색만 .clear를 해주면 되는거 아닌가?

그렇게 생각하셨다면 당신은 천재...

 

빌드 해봅시다.

 

으음~! 보기 좋군요

 

자 그러면 마지막에 남은 복병...

요즘에는 복병이라는 단어를 안쓰나... 흠흠 ㅠ

 

빈곳 눌렀을때는 배경색을 안 입히고 싶다

 

5) didSelectItemAt 을 활용하자 

 

자... 생각을 해보면 

클릭했을때 배경색이 바뀌는 부분이 

didSelectItemAt 메소드 안에서 실행되니

여기서 조건만 추가해주면 되겠다!

    func updateDay() {
        // 해당 메서드가 불려지만 빈배열로 만듭니다.
        self.days = []
        // 해당 요일의 시작 인덱스를 정해주고
        let startOftheWeek = startDayOftheWeek()
        // 시작 일수와 + 해당 달의 일수를 더해줍니다.
        let totalDay = startOftheWeek + endDate()
        
        for day in Int()..<totalDay {
            if day < startOftheWeek {
                days.append(String())
                continue
            }
            self.days.append("\(day - startOftheWeek + 1)")
        }
        print("배열 생김: ",days)
        collectionView.reloadData()
    }

/* 
배열 생김:  ["", "", "", "", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
"23", "24", "25", "26", "27", "28", "29", "30"]
*/

 

이 함수 기억하시나요? 

여기서 배열 안에 하나씩 생기면서 배열이 완성이 됩니다.

 

옳거니!! 

String(숫자)로 되어있으니

Int일때만 클릭하면 되겠구나! 

 

바로 코드를 작성해봅니다.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath)
        if !days[indexPath.item].isEmpty {
            cell?.backgroundColor = .yellow
        }
    }

 

아주 심플합니다...

여기서 다시한번 days[indexPath.item]의 

의미에 대해 깊게 이해할 수있었습니다.

 

 

자. 빌드해봅시다. 

 

음... 마우스의 위치가 안보이는게 흠이긴 하지만

잘 작동합니다.

 

 

 

다음에는 클릭했을때 Cell을 꾸밀수 있게 해보겠습니다!

'Swift' 카테고리의 다른 글

iOS Cutsom Calendar 구현하기 4  (0) 2023.04.18
iOS Custom Calendar 구현하기 3  (2) 2023.04.18
iOS Custom Calendar 구현하기2  (0) 2023.04.17
iOS Custom Calender 구현하기  (2) 2023.04.17
어서와 SwiftUI @FetchRequest는 처음이지?  (0) 2023.03.23