ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 할일 리스트(To-Do List) 앱
    iOS/패스트캠퍼스(앱제작) 2022. 4. 3. 13:33

    최종 완성본

    < 주요기능 >

    1.  + 버튼 클릭:  할일 등록

    2.  할일 클릭 시 체크 버튼 활성화

    3. 스와이프로 delete

    4. edit버튼 / delete

    5. 할일 순서 재정렬

    6. 앱 재실행 시 직전까지 저장한 내용 보여주기 : userDefault

       (로컬에 저장한 할일 불러오기)


     

    1. 할일 등록 기능 구현

    - 할일 내용과 완료 여부를 저장할 구조체 선언 (별도의 swift파일)

    // Task.swift
    
    import Foundation
    
    struct Task {
        var title: String // 할일의 내용 저장
        var done: Bool // 할일 완료 여부 저장
    }

    - 등록 버튼 클릭 시 할일이 등록됨

    //
    //  ViewController.swift
    //  ToDoList
    //
    //  Created by YANG on 2022/04/03.
    //
    
    import UIKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var tableView: UITableView!
        // 할일을 저장하는 배열 생성
        var tasks = [Task]()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            self.tableView.dataSource = self
        }
    
        @IBAction func tabEditBtn(_ sender: UIBarButtonItem) {
        }
        
        
        @IBAction func tabAddBtn(_ sender: UIBarButtonItem) {
            let alert = UIAlertController(title: "할 일 등록", message: nil, preferredStyle: .alert)
            // 등록 버튼을 누를때마다 할일 등록 -> handler내에 closure정의
            let registerBtn = UIAlertAction(title: "등록", style: .default, handler: { [weak self] _ in
                // textField에 입력된 값을 가져오기
                guard let title = alert.textFields?[0].text else { return }
                let task = Task(title: title, done: false)
                self?.tasks.append(task)
                // 할일이 추가될때마다 테이블뷰 reload -> 할일이 표시되도록
                self?.tableView.reloadData()
            })
            
            let cancleBtn = UIAlertAction(title: "취소", style: .cancel, handler: nil)
            alert.addAction(cancleBtn)
            alert.addAction(registerBtn)
            
            // closure: alert을 표시하기 전, textfield를 구성(설정)하기 위함.
            alert.addTextField(configurationHandler: { textField in
                textField.placeholder = "할 일을 입력해주세요"
            })
            
            self.present(alert, animated: true, completion: nil);
        }
    }
    
    extension ViewController: UITableViewDataSource {
        // 두가지 필수 메소드 구현
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.tasks.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            let task = self.tasks[indexPath.row]
            cell.textLabel?.text = task.title
            return cell
        }
    }

     

    2. UserDefault 설정 -> 앱 종료 후 재실행 시 사용자의 정보 load

        // 1. 등록한 할일을 userDefault에 저장하는 함수
        func saveTasks() {
            // map을 통해 배열 요소를 딕셔너리 형태로 mapping
            let data = self.tasks.map {
                [
                    "title": $0.title,
                    "done": $0.done
                ]
            }
            let userDefaults = UserDefaults.standard
            userDefaults.set(data, forKey: "tasks")
        }
        
        // 2. userDefault에 저장된 할일들을 load
        func loadTasks(){
            let userDefaults = UserDefaults.standard
            guard let data = userDefaults.object(forKey: "tasks") as? [[String: Any]] else { return }
            self.tasks = data.compactMap {
                guard let title = $0["title"] as? String else { return nil }
                guard let done = $0["done"] as? Bool else { return nil }
                return Task(title: title, done: done)
            }
        }

    - 프로퍼티 옵저버(didSet, willSet)를 통해, tasks배열에 할일(값)이 들어올 때마다 saveTasks()호출 -> userDefault에 값 저장

    class ViewController: UIViewController {
    
        @IBOutlet weak var tableView: UITableView!
        // 할일을 저장하는 배열 생성
        var tasks = [Task]() {
            didSet {
                self.saveTasks()
            }
        } // 3. 프로퍼티 옵저버 : tasks배열에 할일이 추가될 때마다 userDefault에 할일이 저장됨
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.tableView.dataSource = self
            self.loadTasks() // 4. userDefault에 저장된 할일 불러오기
        }

     

    3. 할일 완료표시 (체크마크) 생성

    - tasks배열의 done 프로퍼티에 값 설정 ( false -> true, true -> false)

    - delegate를 사용하여 특정 셀에 접근

    extension ViewController: UITableViewDelegate {
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            // tasks 인스턴스의 done프로퍼티가 false 이면 true로
            var task = self.tasks[indexPath.row]
            task.done = !task.done
            self.tasks[indexPath.row] = task
            // at: 선택된 row만 reload -> 구조체 배열을 받으므로 여러 행 선택 가능
            // with: cell을 좌/우로 스왑했을때 나타나는 행동
            self.tableView.reloadRows(at: [indexPath], with: .automatic)
        }
    }

    - dataSource를 사용하여 셀에 체크마크 표시

    extension ViewController: UITableViewDataSource {
        // 두가지 필수 메소드 구현
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.tasks.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            let task = self.tasks[indexPath.row]
            cell.textLabel?.text = task.title
            
            if task.done {
                cell.accessoryType = .checkmark
            } else {
                cell.accessoryType = .none
            }
            
            return cell
        }

    4. 할일 수정 기능 

    - edit버튼 클릭시 done버튼 활성화 / 편집 가능 모드
    - done버튼 클릭시 다시 edit버튼 활성화 / 편집 가능 모드 해제

        override func viewDidLoad() {
            super.viewDidLoad()
            self.tableView.dataSource = self
            self.tableView.delegate = self
            self.loadTasks() // 4. userDefault에 저장된 할일 불러오기
            
            // done버튼 생성
            self.doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneBtnTap))
        }
        
        @objc func doneBtnTap() {
            self.navigationItem.leftBarButtonItem = self.editButton
            // 편집모드 해제
            self.tableView.setEditing(false, animated: true)
        }
    
        @IBAction func tabEditBtn(_ sender: UIBarButtonItem) {
            guard !self.tasks.isEmpty else { return }  // tableCell이 비어있지 않을 때만 편집모드 활성화 되도록 방어코드
            self.navigationItem.leftBarButtonItem = self.doneButton
            // tableCell이 편집모드가 되도록 설정
            self.tableView.setEditing(true, animated: true)
        }

     

    5. 할일 삭제, 재정렬

    extension ViewController: UITableViewDataSource {
        // 두가지 필수 메소드 구현
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.tasks.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            let task = self.tasks[indexPath.row]
            cell.textLabel?.text = task.title
            
            if task.done {
                cell.accessoryType = .checkmark
            } else {
                cell.accessoryType = .none
            }
            
            return cell
        }
        
        // 편집모드에서 삭제 버튼을 눌렀을 때, 삭제 버튼을 누른 셀이 어떤 셀인지 알려주는 메소드
        func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
            // 선택된 행의 tasks배열 삭제
            self.tasks.remove(at: indexPath.row)
            // tableView에서도 삭제
            tableView.deleteRows(at: [indexPath], with: .automatic)
            
            if self.tasks.isEmpty {
                self.doneBtnTap()
            }
        }
        
        // 편집모드에서 cell 재정렬
        func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
            return true
        }
        
        // sourceIndexPath: 원래 있었던 위치, destinationIndexPath: 이동한 위치
        func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
            // tasks 배열도 재정렬
            var tasks = self.tasks
            let task = tasks[sourceIndexPath.row]
            tasks.remove(at: sourceIndexPath.row)
            tasks.insert(task, at: destinationIndexPath.row)
            self.tasks = tasks
        }

    'iOS > 패스트캠퍼스(앱제작)' 카테고리의 다른 글

    날씨 앱  (0) 2022.05.08
    타이머 앱  (0) 2022.05.08
    일기장 앱  (0) 2022.04.20
    계산기 앱  (0) 2022.04.03
    LED전광판 앱  (0) 2022.04.01

    댓글

Designed by Tistory.