-
-
Save sooop/6fb0fbe501511e174e3be97e4d2fe14f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import CoreData | |
/// 디테일뷰에서 편집이 끝났을 때 이벤트를 처리할 델리게이트를 위한 프로토콜 | |
protocol ANMemoEditorDelegate: class { /// 델리게이트는 `weak`여야 하므로 클래스에만 적용되어야 한다. | |
func editorDidFinishedEditing(_ sender: Any) | |
} | |
class ANListViewController: UITableViewController, ANMemoEditorDelegate | |
{ | |
/// Xcode8에서는 엔티티가 자동으로 클래스로 변환됨. | |
/// 이전버전과 같이 수동으로 NSManagedObject 클래스를 생성하면 | |
/// 중복 정의로 오류발생 | |
var memo: Memo? | |
/// iOS10부터 코어데이터 스택을 생성하는 방법이 NSPersistentContainer를 | |
/// 사용하도록 변경됨 | |
/// 따라서 앱델리게이트로의 `persistentConatiner` 속성으로부터 | |
/// 컨텍스트를 얻을 수 있음. | |
lazy var context: NSManageObjectContext = { | |
return (UIApplication.shared as! AppDelegate) | |
.persistentContainer.viewContext | |
}() | |
/// 메모리스트는 computed proprety. | |
var memoList: Array<Memo> { [unowned self] in | |
/// NSManagedObject 클래스는 이제 | |
/// 1. 연결된 엔티티가 누군지 알고 있고 | |
/// 2. NSFetchResultType<T> 프로토콜을 적용받는다. | |
/// 따라서 fetchRequest는 이로부터 간단히 생성된다. | |
let fetchRequest = Memo.fetchRequest() | |
fetchRequest.sortDescriptors = [NSSortDescriptor(key:"lastModifiedDate", asceding: false)] | |
do { | |
return (try self.context.fetch(fetchRequest)) as! [Memo] | |
} catch { | |
return [] | |
} | |
} | |
/// ANMemoEditorDelegate | |
/// 디테일뷰에서 편집이 끝나면 컨텍스트의 내용을 저장하고 | |
/// 테이블 뷰를 리로드한다. | |
func editorDidFinishedEditing(_ sender: Any) { | |
try? context.save() | |
tableView.reloadData() | |
} | |
func numbersOfSections(in tableView: UITableView) -> Int { | |
return 1 | |
} | |
func tableView(_ tableView: UITableView, numberOfRowsInSection: Int) -> Int { | |
return memoList.count | |
} | |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
/// 테이블 뷰의 재사용셀에 대해 클래스를 등록해두면 | |
/// 재사용할 셀이 부족한 경우 테이블 뷰가 자동으로 셀을 생성한다. | |
tableView.register(UITableViewCell.self, forCellReuseIdentifier:"MemoListCell") | |
/// 따라서 셀은 옵셔널 타입이 아님. | |
let cell = tableView.dequeueReusableCell(identifier:"MemoCellList", for: indexPath) | |
let currentMemo = memoList[indexPath.row] | |
let df = { | |
let formatter = DateFormatter() | |
formatter.dateStyle = .none | |
formatter.timeStyle = .short | |
return formatter | |
}() | |
cell.textLabel?.text = currentMemo.title | |
/// Memo의 각 프포퍼티값들은 옵셔널로 동작한다. | |
/// 특히 Date 의 타입은 Date가 아니라 NSDate임. | |
if let date = currentMemo.date { | |
cell.detailTextLabel?.text = df.string(from: date as Date) | |
} else { | |
cell.detailTextLabel?.text = "" | |
} | |
return cell | |
} | |
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { | |
guard let identifier = segue.identifier else { | |
super.prepare(for: segue, sender: sender) | |
return | |
} | |
switch identifier { | |
case "addMemoSegue": | |
let destination = (segue.destination as! DetailViewController) | |
let newMemo = Memo(context: self.context) | |
destination.delegate = self | |
destination.currentMemo = newMemo | |
case "viewDetailSegue": | |
let selectedMemo = memoList[tableView.indexPathForSelectedRow!.row] | |
let destination = (segue.destination as! DetailViewController) | |
destination.currentMemo = selectedMemo | |
destination.delegate = self | |
default: | |
super.prepare(for:segue, sender:sender) | |
} | |
} | |
} | |
class ANDetaileViewController: UIViewController { | |
weak var delegate: ANMemoEditorDelegate? | |
var currentMemo: Memo? | |
@IBOutlet weak var titleField: UITextField! | |
@IBOutlet weak var contentView: UITextView! | |
/// 완료를 탭했을 때 | |
@IBAction func doneTapped(_ sender: Any?) { | |
currentMemo?.title = titleField.text ?? "no title" | |
currentMemo?.content = contentView.text ?? "" | |
let now = Date() as NSDate | |
currentMemo?.lastModifiedDate = now | |
currentMemo?.createDate = currentMemo.createDate ?? now | |
delegate?.editorDidFinishedEditing(self) | |
navigationController?.popViewController(animated: true) | |
} | |
@IBAction func cancelEdit(_ sender: Any?) { | |
navigationController?.popViewController(animated: true) | |
} | |
override viewWillAppear(_ animated: Bool) { | |
titleField.text = currentMemo?.title | |
contentView.text = currentMemo?.content | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment