본문 바로가기

𝗔𝗦𝗦𝗜𝗚𝗡𝗠𝗘𝗡𝗧/[내배캠] 4주차 - ToDo

[내일배움캠프] iOS 입문 과제 - My Todo List(02)

 

 

 

 

 

My Todo List

 

 

어제 그리고 오늘은 ToDo 내용 수정과 메모 추가 기능을 만들었다.

 

 

'사실 처음에는 또 쉽겠지(ㅋ)' 하고 쉽게 봤다.

그렇다. 또 큰 코를 다치고 말았다. 난 지금 코가 없다.

 

 

 

 

코가 없어진 과정에 대해,

 

 

 

 

처음 생각은 그랬다,

 

 

'변수를 추가하고 테이블 뷰에 사용자가 입력한 값을 ViewController로 전달해 구조체의 값을 변경하면 되겠지.'

 

 

...누구나 그럴듯한 계획은 가지고 있다. 생각만으로는 지구정복도 가능하다는 사실을 망각한 대가가 너무 크다.

 

 

 

 

ToDo 수정 및 MeMo 기능(+ Placeholder)

 

 

ViewController.swift

struct TodoItem {
    static var nextId = 1 
    var id: Int
    var title: String
    var isCompleted: Bool
    var memo: String?
    var saveDate: String

    init(title: String, isCompleted: Bool = false, date: Date = Date(), memo: String? = nil) {
        self.id = TodoItem.nextId
        self.title = title
        self.isCompleted = isCompleted
        self.memo = memo

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy년 MM월 dd일"
        self.saveDate = dateFormatter.string(from: date)

        TodoItem.nextId += 1 // 아이디 +1
    }
}


// 생략 


func detailViewControllerDidSave(todoItem: TodoItem) {
    if let index = todos.firstIndex(where: { $0.id == todoItem.id }) {
        todos[index] = todoItem

        if let tableView = tableView {
            tableView.reloadData()
        } else {
            print("tableView가 nil입니다.")
        }
    }
}

 

메모에 대한 값을 저장하기 위해 제일 먼저 구조체에 변수를 추가했다. 그리고, DetailViewController에서 수정된 TodoItem을 저장할 때 호출할 메서드를 작성했다. 수정된 TodoItemid를 사용하여 todos 배열에 해당 아이템의 인덱스를 찾고, 수정된 TodoItem으로 해당 아이템을 업데이트, tableView가 있는 경우 리로드 하여 변경사항을 반영하도록 하였다.

 

 

- 수정된 TodoItemid를 사용하여 todos 배열에서 해당 아이템의 인덱스 찾기

TodoItem의 해당되는 위치에 아이템 업데이트

 

- tableView가 있는 경우

해당 테이블 뷰를 리로드 하여 변경 사항을 반영

만약 tableViewnil이라면 콘솔에 메시지 출력

 

 

 

 

DetailViewController.swift

// DetailViewController의 수정된 Todo 아이템을 저장하는 데 사용되는 메서드를 정의한 protocol
protocol DetailViewControllerDelegate: AnyObject {
    func detailViewControllerDidSave(todoItem: TodoItem)
}

class DetailViewController: UIViewController, UITextViewDelegate {

    // delegate 속성 선언
    weak var delegate: DetailViewControllerDelegate?

    // 생략 

    var todoItem: TodoItem? // 전달된 TodoItem을 저장할 변수

    // 생략 

    // MARK: - Save Button Action / ToDo 수정 및 메모 저장 동작

    @IBAction func saveButtonTapped(_ sender: UIBarButtonItem) {
        // 텍스트뷰가 비어 있는지 확인
        guard let text = textView.text, !text.isEmpty else {
            // 텍스트뷰가 비어 있으면 알림 표시
            let alertController = UIAlertController(title: "알림", message: "ToDo를 입력해 주세요.", preferredStyle: .alert)
            let okAction = UIAlertAction(title: "확인", style: .default, handler: nil)
            alertController.addAction(okAction)
            present(alertController, animated: true, completion: nil)
            return
        }

        // 수정된 TodoItem 생성
        var updatedTodoItem = todoItem ?? TodoItem(title: "") // 기존 TodoItem이 없으면 빈 TodoItem 생성

        // 수정된 값을 TodoItem의 title에 저장
        updatedTodoItem.title = text

        // 입력된 값을 TodoItem의 memo에 저장
        updatedTodoItem.memo = memoView.text

        // delegate를 통해 수정된 TodoItem을 ViewController로 전달
        delegate?.detailViewControllerDidSave(todoItem: updatedTodoItem)

        // 이전 화면으로 이동
        navigationController?.popViewController(animated: true)
    }
}

 

DetailViewController에서는 수정된 Todo 아이템을 저장하는 데 사용하는 메서드를 정의한 protocol를 작성했다. DetailViewControllerDelegate 프로토콜을 준수하는 객체를 약한 참도로 저장하는 속성을 가진 delegate를 선언했다. 그리고 todoItem 변수를 선언하여 저장 버튼 클릭 시 호출되는 saveButtonTapped(\_:) 함수를 구현했다. 먼저 텍스트 뷰의 isEmpty 여부를 확인하고 비어있다면 알림을 표시, 그렇지 않을 경우 입력된 값들을 TodoItem 저장, 수정된 TodoItemdelegate을 통해 전달하도록 했다.

 

 

- DetailViewControllerDelegate 프로토콜

detailViewControllerDidSave(todoItem:) 메서드 요구

수정된 TodoItem을 저장하기 위해 사용

 

- DetailViewController 클래스

UIViewController를 상속받음

UITextViewDelegate 프로토콜을 따름

 

- delegate

DetailViewControllerDelegate 프로토콜을 준수하는 객체를 약한 참조로 저장

 

- todoItem 속성은 전달된 TodoItem 저장

- saveButtonTapped(\_:)

저장 버튼이 눌렸을 때 호출

텍스트뷰가 비어 있는지 확인하고 비어 있다면 알림 표시

그렇지 않을 경우, 입력된 값들을 TodoItem 객체에 저장, 수정된 TodoItemdelegate를 통해 전달

 

 

 

 

그러니까, 이렇게 하면 되는데 계속 데이터가 변경되지 않아서 어제도 오늘도 내내 이 코드 내에서 뭐가 잘못된 건지 몰라서 한참을 헤맸다.

 

 

근데 확인해 보니

 

스토리보드에서 tableView 아웃렛이 제대로 연결이 안 되어있었다. ᕕ( ᐛ )ᕗ

진짜 황당하고... 분명 연결했다고 생각했는데 아니었다.

 

어쨌든 해결완료! 이제 ToDo 수정과 Memo를 남길 수 있게 되었다.

 

 

 

 

Placeholder 설정

memoView.text = placeholderText
memoView.textColor = UIColor.lightGray

// 생략 

func textViewDidBeginEditing(_ textView: UITextView) {
    if memoView.text == placeholderText {
        memoView.text = ""
        memoView.textColor = UIColor.black
    }
}

func textViewDidChange(_ textView: UITextView) {
    if memoView.text.isEmpty {
        memoView.text = placeholderText
        memoView.textColor = UIColor.lightGray
    }
}

 

이틀간 헤매던 걸 해결한 기쁨으로 간단하게 placeholder까지 설정해 줬다.

 

 

- memoView.textplaceholderText를 할당하여 플레이스홀더를 설정

- textViewDidBeginEditing(\_:)

텍스트 뷰가 편집 모드로 전환될 때 호출

이때, 텍스트 뷰에 입력이 감지될 경우 placeholder를 지우고 텍스트가 입력됨

 

- textViewDidChange(\_:)

텍스트 뷰의 내용이 변경될 때마다 호출

여기서는 텍스트 뷰가 비어 있는 경우 플레이스홀더를 다시 표시

 

 

 

 

늘 느끼지만 한 번 더, 꼭 확인하자.

 

 

 

 

 

 

 

 

 

Recent Posts
Visits
Today
Yesterday
Archives
Calendar
«   2024/10   »
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 31