iOS/Toy project

[iOS : Toy Project] Todo List 만들기 (5)

yevdev 2022. 8. 19. 20:46

이전 포스팅

- TodoList(1)

- TodoList(2)

- TodoList(3)

- TodoList(4)

 

 

자세한 코드는 여기로!

 

GitHub - yexjin/iOS_Study: iOS 토이프로젝트 모음집📱

iOS 토이프로젝트 모음집📱. Contribute to yexjin/iOS_Study development by creating an account on GitHub.

github.com

 

 

 

8/19

이제 할 일은 Todo가 완료되었을 경우, 버튼 동작 등을 구현해보는 일!

 

 

1️⃣ checkButton selected 상태 설정

→ Button을 클릭해서 inspector의 State Config 를 Seleted로 설정하고, Image를 "checkmark.circle" 로 설정

→ Control의 State에 Selected를 체크해주자

 

 

 

 

2️⃣ strikeThrouwView 만들기

일단 할 일을 완료했다는 체크버튼을 눌렀을 때 가로 취소선을 storyboard에서 만들어 놓고,

기본 View를 통해, AutoLayout 설정

 

CollectionViewCell에 IBOutlet 설정을 통해 storyboard 컴포넌트 연결

@IBOutlet weak var strikeThroughView: UIView!
@IBOutlet weak var strikeThroughWidth: NSLayoutConstraint!

→ strikeThroughWidth 는 체크가 되었을 때와 안되었을 때 width를 설정해줌으로써 화면에 나타나게 or 나타나지 않게 보일 수 있음

    private func showStrikeThrough(_ show: Bool) {
        if show {
            strikeThroughWidth.constant = descriptionLabel.bounds.width
        } else {
            strikeThroughWidth.constant = 0
        }
    }

→ 바로 이렇게!

descriptionLabel.bounds.width : descriptionLabel View의 영역(bounds)의 너비(width)

 

그리고 cell 업데이트 로직에 showStrikeThrough 메소드 추가

 func updateUI(todo: Todo) {
        // TODO: Todo Cell 업데이트
        checkButton.isSelected = todo.isDone
        descriptionLabel.text = todo.detail
        descriptionLabel.alpha = todo.isDone ? 0.2 : 1
        deleteButton.isHidden = todo.isDone == false
        showStrikeThrough(todo.isDone)
    }

 

 

이렇게 일단 제거 표시줄 (취소선?) 만들기 끝!

 

 

 

3️⃣ reset() 메소드

    func reset() {
        // TODO: reset로직 구현
        descriptionLabel.alpha = 1
        deleteButton.isHidden = true
        showStrikeThrough(false)
    }

alpha : 선명도

 isHidden : 숨김 

이 로직에 대해선 좀이따 checkButton, deleteButton의 동작을 다루는데서 자세히 알아보자

 

암튼, reset() 메소드는 언제 실행?

    override func awakeFromNib() {
        super.awakeFromNib()
        reset()
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        reset()
    }

 awakeFromNib() : 화면이 storyboard에서 띄워졌을 때

 prepareForReuse() : 재사용을 위한 준비를 할 때

 

 

 

4️⃣ 이제 checkButton, deleteButton 동작을 다뤄보자

이미 checkButton과 deleteButton의 컴포넌트 연결은 되어있고,

IBAction을 통해 버튼 이벤트가 발생할 경우 취할 Action을 정의해보자

잠깐, IBOutlet이랑 IBAction은 무엇?
💡IBOutlet
- @IBOutlet 키워드를 통해 Storyboard에서 만든 Label, Image 등 컴포넌트 연결
- 값에 접근하기 위한 변수라고 생각하자
💡IBAction
- @IBAction 키워드를 통해 Event가 일어날 경우 호출되는 Action을 정의

 

➰checkButtonTapped

@IBAction func checkButtonTapped(_ sender: Any) {
    // TODO: CheckButton 처리
    checkButton.isSelected = !checkButton.isSelected
    let isDone = checkButton.isSelected
    showStrikeThrough(isDone)
    descriptionLabel.alpha = isDone ? 0.2 : 1
    deleteButton.isHidden = !isDone
    doneButtonTapHandler?(isDone)
}

 alpha와 isHidden에 대해선 위에서 정의

 

 isDone은 checkButton이 눌렸을 때 true인데, 즉 deleteButton은 checkButton이 눌리지 않았을 땐 안보이고 눌렸을 때만 삭제버튼이 보이게 되는 로직

 

 doneButtonTapHandler : 실제 데이터 변경을 위한 Closure 로, isDone을 넘김으로써 실제 Todo 객체를 업데이트 할 지 말지 정하게 된다.

 

 

➰deleteButtonTapped

@IBAction func deleteButtonTapped(_ sender: Any) {
    // TODO: deleteButton 처리 
    deleteButtonTapHandler?()
}

→ 실제 데이터를 지우는 작업을 위한 틀만 closure을 이용하여 만들어둠

 

 

이 두 메소드 (deleteButtonTapped, checkButtonTapped) 에서 deleteButtonTapHandler, doneButtonTapHandler는 cell안에 있는 클로저이다. (189, 190 라인)

cell 객체

 

📌 왜 클로저로 만들었나?

→ 굳이 Cell을 보여주는 View에서 깊은 로직까지 다루는 건 복잡해보여서 인거 같음..! 

 

그럼 클로저 들의 실행은 어디서?

CollectionView의 DataSource 객체에서!

 

 

 

🚀 구현 완료

 

 

 

스터디 시작 1시간 20분 전,, ㅋㅋㅋㅋ 일단 대충 끝! 

이것저것 활동할 것도 있고 알바도 이번주에 왕많아서 좀 버거웠는데

블로그에 글도 하나씩 꼬박꼬박쓰고 완성까지해서 진짜 왕 뿌듯하다 😊

 

 

다음주 스터디 과제로 뭐 내주실지 설레고 무섭다..