Programming/iOS

[iOS/Swift3.0] iOS TodoList App 만들기 6 (데이터 영구 저장)

devssun 2017. 9. 27. 23:35
728x90
반응형

Let's make iOS TodoList App (TodoList App 만들기)

그동안 배운 것을 활용해보기 위해 할일을 적고 체크하는 TodoList 앱을 만들어보기로 합니다.

  • 구현 기능

    • Todo List 조회 ✔️
    • Todo 등록 ✔️
    • Todo 삭제 ✔️
    • Todo 완료 체크 ✔️
  • 사용할 것

    • Navigation Controller
    • UIBarButtonItem
    • Auto Layout
    • UserDefaults (데이터 영구 저장)
    • UITableView (리스트 출력)
    • UITextField, UITextView (Todo 등록)



지난 시간까지 TodoList 앱에 있을 조회, 등록, 삭제, 완료 기능을 구현하였습니다 지금 앱은 앱을 완전히 종료 후 다시 실행하면 기존에 입력했던 데이터가 사라집니다 왜냐하면 list변수는 앱이 종료되면 없어지는 생명주기를 갖고 있기 때문입니다 Todo를 체크해야하는데 리스트가 없어지면 안되겠죠? 이번엔 list를 저장하도록 합시다

그래서 우리는 UserDefaults를 사용해서 list를 영구 저장하도록 합니다 이 데이터는 앱을 삭제할 때까지 남아있게 됩니다. 안드로이드에서 SharedPreference와 비슷한 역할을 가집니다


  • UserDefault를 사용하여 구현할 기능입니다
    1. 앱 실행 시 저장된 데이터 불러오기
    2. 뷰가 다시 그려질 때 현재 데이터 저장하기

먼저 데이터를 저장하는 소스를 작성하겠습니다 userDefault에 list를 바로 인자로 보내면 에러가 발생하여 [String: AnyObject] 형태로 배열을 새로 만들어 넣어주도록 하겠습니다


// userdefault 저장
    func saveAllData() {
        let data = list.map {
            [
                "title": $0.title,
                "content": $0.content!,
                "isComplete": $0.isComplete
            ]
        }
 
        let userDefaults = UserDefaults.standard
        userDefaults.set(data, forKey: "items") // 키, value 설정
        userDefaults.synchronize()  // 동기화
    }

[Swift - map]

컨테이너 내부의 기존 데이터를 변형(transform)하여 새로운 컨테이너를 생성하는 고차함수입니다.

list의 요소를 가져와 key를 지정하고 value를 준 뒤 data에 넣어줍니다 그러면 data는 Array<Dictionary<String, Any>> 타입을 가집니다

$0는 타입 추론에 따라 바꿔 사용할 수 있습니다

Reference https://www.youtube.com/watch?v=HmabXrK2tRo




새롭게 loadAllData()라는 함수를 정의하여 앱 실행시 저장된 데이터를 불러오는 기능을 구현하겠습니다 앞서 저장했던 userDefaults의 key인 items로 데이터를 가져옵니다 가져올 때 guard 문법으로 값이 있는지 확인하고 없다면 빠른 종료를 하게 합니다

값이 존재한다면 데이터는 다시 map 함수를 통해 가져오겠습니다


// userDefault 데이터 불러오기
    func loadAllData() {
        let userDefaults = UserDefaults.standard
        guard let data = userDefaults.object(forKey: "items") as? [[String: AnyObject]] else {
            return
        }
 
        print(data.description)
 
        // list 배열에 저장하기
        print(type(of: data))
        list = data.map {
            var title = $0["title"] as? String
            var content = $0["content"] as? String
            var isComplete = $0["isComplete"] as? Bool
 
            return TodoList(title: title!, content: content!, isComplete: isComplete!)
        }
    }


loadAllData()는 뷰가 최초로 그려질 때 실행되야 하므로 viewDidLoad에서 호출하고 saveAllData()는 뷰가 그려질 때 호출되는 viewDidAppear함수에서 실행시킵니다

이렇게 하면 데이터의 영구 저장이 가능합니다 앱을 실행시켜 데이터를 입력한 후 다시 build하여 실행시켜봅시다. 좀 전에 입력한 데이터가 그대로 나오는 것을 확인할 수 있습니다




여기까지 TodoList 앱을 구현하였습니다. 작은 앱인데도 기능 하나씩 작성하니 할 일이 많습니다.

그런데 userdefault에 저장하는 데이터는 viewDidAppear에서만 실행되는데 row를 선택해 완료된 Todo로 체크했을 때는 viewDidAppear는 실행되지 않기 때문에 체크했어도 다시 실행하면 체크가 풀린채 나옵니다

이것은 list 변수에 대한 변경이 필요한 부분입니다


일단 끝! 😇


👉프로젝트의 소스는 gitHub에서 확인가능합니다 https://github.com/hyesunzzang/TodoList 👏🙌🌟



이 프로젝트의 아이디어와 약간의 소스를 참고하였습니다

https://devxoul.gitbooks.io/ios-with-swift-in-40-hours/content/Chapter-4/

반응형