반응형

model에 추가

coreData클래스와 우리가 만들었던 클래스가 충돌하기 때문에, 우리가 만들었던 클래스를 주석처리한다.

//
//  Model.swift
//  NhMemo
//


import Foundation

//class Memo {
//    var content:String
//    var insertDate:Date
//
//    init(content:String) {
//        self.content = content
//        insertDate = Date()
//    }
//
//    //더미 데이터
//    static var dummyMemoList = [
//        Memo(content: "dw memo desu"),
//        Memo(content: "so death gga?")
//
//    ]
//}

2. 코드가 불필요하게 복잡해질 수 있으니, AppDelegate 파일의 주석 처리되어 있는

 // MARK: - Core Data stack

의 밑의 코드를 모두 복사한 후, DataManager이라는 swift파일을 만들어준다.

//
//  DataManager.swift
//  NhMemo


import Foundation
import CoreData

//싱글톤
class DataManager {
    //공유 인스턴스를 저장할 타입 프로퍼티 추가
    static let shared = DataManager()
    
    //생성자 : 이렇게 하면, 하나의 인스턴스로 앱 전체에 공유할 수 있다.
    private init() {
        
    }
    
    //메모를 저장할 배열을 생성 후 빈배열로 만듬.
    var memoList = [Memo]()
  
    
    //새로운 속성 추가 : 대부분의 작업은 context가 담당
    var mainContext: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    
    
    func fetchMemo() {
    
        //데이터베이스에서 데이터를 읽기 위해 fetch request를 만들어야한다.
        let request:NSFetchRequest<Memo> = Memo.fetchRequest()
        
        //데이터 정렬해주어야함 : 내림차순 정렬
        let sortByDateDesc = NSSortDescriptor(key: "insertDate", ascending: false)
        
        request.sortDescriptors = [sortByDateDesc]
        
        //fetch 메소드는 context가 제공하는 fetch 메소드를 사용.
        do {
            memoList = try mainContext.fetch(request)
        }catch {
            print(error)
        }
       
    }
    
    //메모추가
    func addNewMemo(_ memo:String?) {
        //코어 데이터
        let newMemo = Memo(context: mainContext)
    
        newMemo.content = memo
        newMemo.insertDate = Date()
        
        //메모 호출
        memoList.insert(newMemo, at: 0)
        
        //메모 저장 컨텍스트
        saveContext()
    }
    
    
    //MARK: - Core Data stack
    lazy var persistentContainer: NSPersistentContainer = {
      
        
        let container = NSPersistentContainer(name: "NhMemo")
        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)")
            }
        }
    }
}

에러 수정

3. compostViewController에서 에러가 나는 부분 주석처리

//
//  ComposeViewController.swift
//  NhMemo
//


import UIKit

class ComposeViewController: UIViewController {

    //cancel 버튼 연결
    @IBAction func close(_ sender: Any) {
        //첫번째 파라미터 : true전달 시, 실행
        //두번째 파라미터 : 어떤 함수를 실행시키고 싶을 때, 클로저로 
        dismiss(animated: true, completion: nil)
    }
    
    //textView 저장을 위한 연결
    @IBOutlet weak var memoTextview: UITextView!
    
    //save 버튼 연결
    @IBAction func save(_ sender: Any) {
        
        //저장 버튼 클릭 시, memo안에 텍스트 저장 및 조건문 
        guard let memo = memoTextview.text,
              memo.count > 0 else {
                  //확장클래스 가져옴. 사용자가 메모를 입력하지 않을 시, 경고창 뜸
                  alert(message: "메모를 입력하세요.")
                  return
              }
        //guard 다음에 실행 됨.
//        let newMemo = Memo(content: memo)
//        //메모 저장
//        Memo.dummyMemoList.append(newMemo)
        DataManager.shared.addNewMemo(memo)
        
        //화면 닫기 전, notification 전달 (update를 위한 전달 broadcast)
        NotificationCenter.default.post(name: ComposeViewController.newMemoDidInsert, object: nil)
        
        //창 닫음
        dismiss(animated: true, completion: nil)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
    
    }

    

}

extension ComposeViewController {
    //notification : 이름으로 구분
    static let newMemoDidInsert = Notification.Name(rawValue: "newMemoDidInsert")
}

4. memo list table view controller 에러 수정

//
//  MemoListTableViewController.swift
//  NhMemo
//


import UIKit

class MemoListTableViewController: UITableViewController {
    
    //날짜 포맷 (클로저 사용)
    let formatDate:DateFormatter = {
       let f = DateFormatter()
        f.dateStyle = .long //long으로 출력
        f.timeStyle = .short
        f.locale = Locale(identifier: "Ko_kr") //한글로 변경
        return f
    }()
    
    
    //view가 화면에 표시되기전에 실행 됨. 음.. 안드로이드로 치면,, onCreate?
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        DataManager.shared.fetchMemo()
        tableView.reloadData()
      
    }
    
    var token: NSObjectProtocol?
    //옵저버 해제
    deinit {
        if let token = token {
            NotificationCenter.default.removeObserver(token)
        }
    }
    
    //세그웨이에 연결된 화면을 생성하고, 화면을 전환하기 직전에 호출 됨. sender을 활용! (몇번째 cell을 클릭했는지 계산해야함.)
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let cell = sender as? UITableViewCell,
           let indexPath = tableView.indexPath(for: cell) { // 몇번째 cell인지 확인 할 수 있음.
            //목록화면과 보기화면 접근 가능.
            //segue를 실행하는 화면을 source라고 함, 새롭게 표시되는 화면을 destination이라고 함.
            //타입 캐스팅 해야 함.
            if let vc = segue.destination as? DetailViewController {
                vc.memo = DataManager.shared.memoList[indexPath.row]
            }
            
            
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //notification, queue : ui업데이트 메인쓰레드, 4번째 파라미터에 전달된 클로저가 3번째 파라미터에 전달되어 실행됨.
        //옵저버 해제 안하면 메모리 낭비!!
        token = NotificationCenter.default.addObserver(forName: ComposeViewController.newMemoDidInsert, object: nil, queue: OperationQueue.main)
        { [weak self] (noti) in
            //테이블 뷰 리로드
            self?.tableView.reloadData()
        }
       
    }

    // 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 = formatDate.string(for: target.insertDate)

        return cell
    }
    

    

}

 

반응형

+ Recent posts