Skip to content

Instantly share code, notes, and snippets.

@sooop
Last active December 28, 2016 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sooop/6fb0fbe501511e174e3be97e4d2fe14f to your computer and use it in GitHub Desktop.
Save sooop/6fb0fbe501511e174e3be97e4d2fe14f to your computer and use it in GitHub Desktop.
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