-
iOS - memo 앱 만들기 #4 목록 업데이트카테고리 없음 2020. 12. 15. 16:30
memo 앱 만들기 (목록 업데이트)
[MemoListTableViewController]
// 뷰 컨트롤러가 관리하는 뷰가 화면에 표시되게 직전에 자동으로 호출 // 근데 viewWillAppear 메소드는 full screen에서만 자동으로 호출되고 ios 13이상의 기본값인 sheet에서는 호출되지 않는다 -> notification을 이용해야 한다 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) reloadData -> 데이터소스가 전달해주는 최신 데이터로 업데이트 tableView.reloadData() print(#function) }
viewWillAppear 메소드는 ios 12까지의 fullScreen에서 자동으로 호출 됐는데
ios13의 sheet 에서는 또 호출이 안된다.. 그래서 Notification으로 전달을 해줘야 원하는 시점에 원하는 이벤트가 발생할 수 있다.
Notification에 대해서 간단하게 말하자면 라디오 방송이라고 할 수 있다.
그리고 라디오 방송국에 해당하는 NotificationCenter가 있다.
라디오 방송국은 주파수로 구별하고 Notification은 name으로 구분한다.
[ComposeViewController]
@IBAction func save(_ sender: Any) { guard let memo = memoTextView.text, memo.count > 0 else{ alert(message: "메모를 입력해주세요") return } let newMemo = Memo(content: memo ) Memo.dummyMemoList.append(newMemo) // Notification을 NotificationCenter에 전달하는부분? NotificationCenter.default.post(name:ComposeViewController.newMemoDidInsert, object: nil) dismiss(animated: true, completion: nil) } extension ComposeViewController{ //라디오방송 -> 방송국에 해당하는 notificationCenter static let newMemoDidInsert = Notification.Name(rawValue: "newMemoDidInsert") }
왜 ComposeViewController에 extension을 추가했냐?
아마 save func이 작동할때 NotificationCenter에 우리가 만든 Notification을 전달하기 위해서 그런것 같다.
Notification은 특정 객체에게 바로 전달되지 않는다.
앱을 구성하는 모든 객체로 전달된다.
이제 save에서 전달한 Notification을 처리해야 하는데 Observer를 등록하고 필요한 코드를 등록하는 식으로 구현한다.
마치 라디오 주파수를 맞추는 것에 비유할 수 있다.
[MemoListTableViewController]
observer를 추가하는 코드는 한번만 실행되면 되기 때문에 viewDidLoad() 에 구현한다
override func viewDidLoad() { super.viewDidLoad() // observer를 실행하는건 한번만 실행하면되서 보통 여기에 한다 //첫번쨰 파라미터로 옵저버를 추가할 notification의 이름 // Notification은 브로드캐스팅 //두번째 는 특별한 이유가없으면 대부분 nil // ui를 업데이트 코드는 반드시 메인쓰레드에서 실행해야한다. // ios는 쓰레드를 직접 처리하지않고 dispatchQueue나 OperationQueue를 통해 처리한다. // 세번째 파라미터로 queue: OperationQueue.main 를해주면 옵저버가 처리하는 쓰레드가 메인 쓰레드에서 처리된다. // 마지막 파라미터에는 closer를 전달한다. // notification이 전달되면 네번째 파라미터로 전달된 클로저가 세번째 파라미터로 전달한 쓰레드에서 실행된다. // notification을 구현하는 코드에서 가장 중요한건 observer를 해제하는것! -> 해제안해도 실행은되지만 내부에서 메모리가 낭비되고 있다. // 지금 밑의 .addObserver()는 옵저버를 해제할수잇는걸 리턴해주는데 보통 이걸 토큰이라 부름 // viewDidLoad에서 추가한 옵저버는 뷰가 화면에서 사라지기 전에 해제하거나 소멸자에서 해제하는데 여기에서는 소멸자에서 해제하겠다 token = NotificationCenter.default.addObserver(forName: ComposeViewController.newMemoDidInsert , object: nil, queue: OperationQueue.main) { [weak self](noti) in self?.tableView.reloadData() } // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem }
이제 viewWillApear에서 구현한 코드는 의미가 없다. 주석처리하거나 삭제
Notification을 구현할때 가장 중요한 부분은 observer를 해제하는 것!
//.addOverserver() 는 observer를 해제할때 사용하는 객체를 리턴해주는데 이걸 보통 token이라고 부름 token = NotificationCenter.default.addObserver(forName: ComposeViewController.newMemoDidInsert , object: nil, queue: OperationQueue.main) { [weak self](noti) in self?.tableView.reloadData()
observer는 view가 화면에서 사라지기 직전에 해제하거나 소멸자에서 해제한다.
여기서는 소멸자를 통해 해제함!
var token : NSObjectProtocol? // 소멸자에서 옵저버 해제 deinit { if let token = token{ NotificationCenter.default.removeObserver(token) } } // viewController가 생성될때 자동으로 호출된다. -> 주로 한번만 실행되는 초기화 코드 실행 override func viewDidLoad() { super.viewDidLoad() // observer를 실행하는건 한번만 실행하면되서 보통 여기에 한다 //첫번쨰 파라미터로 옵저버를 추가할 notification의 이름 // Notification은 브로드캐스팅 //두번째 는 특별한 이유가없으면 대부분 nil // ui를 업데이트 코드는 반드시 메인쓰레드에서 실행해야한다. // ios는 쓰레드를 직접 처리하지않고 dispatchQueue나 OperationQueue를 통해 처리한다. // 세번째 파라미터로 queue: OperationQueue.main 를해주면 옵저버가 처리하는 쓰레드가 메인 쓰레드에서 처리된다. // 마지막 파라미터에는 closer를 전달한다. // notification이 전달되면 네번째 파라미터로 전달된 클로저가 세번째 파라미터로 전달한 쓰레드에서 실행된다. // notification을 구현하는 코드에서 가장 중요한건 observer를 해제하는것! -> 해제안해도 실행은되지만 내부에서 메모리가 낭비되고 있다. // 지금 밑의 .addObserver()는 옵저버를 해제할수잇는걸 리턴해주는데 보통 이걸 토큰이라 부름 // viewDidLoad에서 추가한 옵저버는 뷰가 화면에서 사라지기 전에 해제하거나 소멸자에서 해제하는데 여기에서는 소멸자에서 해제하겠다 token = NotificationCenter.default.addObserver(forName: ComposeViewController.newMemoDidInsert , object: nil, queue: OperationQueue.main) { [weak self](noti) in self?.tableView.reloadData() } // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem }