iOS APP - 메모 앱 #3

longlivedrgn·2022년 8월 18일
post-thumbnail

DB 구현 1(Core Data)

DB를 생성하고, DB 속 데이터를 가져오는 코드를 짜보자!

Entity/ Attribute 생성하기

  • 먼저 아래의 project controller에서 Add Entity를 클릭한다.

  • 새로운 Entity가 생성이 되었으면, 그 entity의 이름을 Memo로 설정을 한다.

  • 그리고 Attribute에서 두개의 Attribute를 만들어 준다.

Scene 및 App delegate 설정하기

  • App Delegate를 보면 아래와 같이 Core Date Stack과 Core Data Saving support가 존재한다.

  • 아래와 같이 주석을 제거해주고 두개의 파트를 잘라내기한다.

DataManager 생성하기

  • DataManager class를 생성해주고, 앞서 두 파트를 붙여넣기 해준다.
    ( 아래의 코드는 주석을 보면서 이해해보기)
class DataManager {
    
    static let shared = DataManager()
    private init() {
        // Singleton 싱글톤
    }
    
    var mainContext: NSManagedObjectContext{
        return persistentContainer.viewContext
    }
    
    // 메모를 데이터베이스에서 읽어오는 코드를 작성해보자
    var memoList = [Memo]()
    
    func fetchMemo() {
        let request: NSFetchRequest<Memo> = Memo.fetchRequest()
        // 날짜를 내림차순으로 정렬해보자.
        let sortByDateDesc = NSSortDescriptor(key: "insertDate", ascending: false)
        request.sortDescriptors = [sortByDateDesc]
        
        // 최종결과가 memoList에 저장이된다. 
        do {
            memoList = try mainContext.fetch(request)
        } catch{
            print(error)
        }
    }
    
    // MARK: - Core Data stack
    
    lazy var persistentContainer: NSPersistentContainer = {
        
        let container = NSPersistentContainer(name: "Memo")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

}
  • Scene Delegate에서 에러가 발생하는데 아래와 같이 코드를 바꿔준다.

그러게 다 만들고, 빌드를 실행해 보면, 에러발생가 발생하는 데 그 이유는 새롭게 만든 entity와 이미 만들어놨던 Model 속 Memo와 충돌이 일어났기 때문이다. 따라서 이제부터 전에 만들었던 Memo class를 수정해주자.

  • 아래와 같이 주석 처리를 해준다.

  • 현재 주석 처리한 Memo.dummyMemoList가 아직 있으므로, 해당 코드들을 DataManager 코드로 변경해준다.

  • 아래와 같이 Datamanager로 변경해 준다.
    // MARK: - Table view data source
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return DataManager.shared.memoList.count
    }

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        // Configure the cell...
        let target = DataManager.shared.memoList[indexPath.row]
        cell.textLabel?.text = target.content
        cell.detailTextLabel?.text = formatter.string(for: target.insertDate)
        
        return cell
    }
  • 앞서 설정한 fetchMemo()를 viewWillAppear에 추가해 준다.
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // 배열이 데이터에 채워지게 한다.
        DataManager.shared.fetchMemo()
        
        // tableView를 업데이트 하기
        tableView.reloadData()
        
//        tableView.reloadData()
    }

// 참고 문헌//
Zedd님 블로그 -
https://zeddios.tistory.com/987
https://zeddios.tistory.com/989?category=682195

DB 구현 2 (Core Data)

  • 새로운 메모를 데이터 베이스에 저장하기

  • DataManager 클래스에 addNewMemo 함수를 생성해준다.

    // 새로운 메모를 데이터 베이스에 저장하기
    func addNewMemo(_ memo: String?){
        // DataManager의 Memo이다.
        let newMemo = Memo(context: mainContext)
        newMemo.content = memo
        // 현재 날자를 그대로 저장하기
        newMemo.insertDate = Date()
        
        saveContext()
    }
  • ComposeViewController에 메모를 데이터 베이스에 저장하는 코드를 추가해준다.
@IBAction func save(_ sender: Any) {
        // memoTextView에 있는 text를 newMemo로 저장!
        guard let memo = memoTextView.text, memo.count > 0 else {
            alert(message: "메모를 입력하세요")
            return
        }
        
//        let newMemo = Memo(content: memo)
//        Memo.dummyMemoList.append(newMemo)
        
        // 데이터 베이스 저장하기!
        DataManager.shared.addNewMemo(memo)
        
        // NotificationCenter Post 설정하기
        NotificationCenter.default.post(name: ComposeViewController.newMemoDidInsert, object: nil)
        
        // 새 메모 창을 닫기
        dismiss(animated: true, completion: nil)
    }

그러나, 시뮬레이터를 실행해보면 데이터베이스에 저장이 되지만 메모리스트에 바로 나오지 않는다! 그 이유는 viewwillappear가 실행되지 않기 때문이다.(sheet로 되어있기에)

  • MemoListTableViewController의 viewWillAppear가 실행이 되지 않는다!
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // 배열이 데이터에 채워지게 한다.
        DataManager.shared.fetchMemo()
        
        // tableView를 업데이트 하기
        tableView.reloadData()
    }
  • 따라서 애초에 memolist에 새로 추가된 memo를 넣어주자!(Datamanager class에)
    // 새로운 메모를 데이터 베이스에 저장하기
    func addNewMemo(_ memo: String?){
        // DataManager의 Memo이다.
        let newMemo = Memo(context: mainContext)
        newMemo.content = memo
        // 현재 날자를 그대로 저장하기
        newMemo.insertDate = Date()
        
        // memoList에 바로 넣어주기
        memoList.insert(newMemo, at: 0)
        
        saveContext()
    }

0개의 댓글