
DetailViewController에서 편집을 할 수 있게 해보자. 그러려면 DetailViewController에서 ComposeViewController와의 관계를 설정해주어야된다.
밑의 toolbar item과 navigation controller를 연결해 준다.

ComposeViewController에 editTarget 변수를 만든다.
var editTarget: Memo?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination.children.first as? ComposeViewController {
vc.editTarget = memo
}
}
override func viewDidLoad() {
super.viewDidLoad()
if let memo = editTarget {
navigationItem.title = "메모 편집"
memoTextView.text = memo.content
} else {
navigationItem.title = "새 메모"
memoTextView.text = ""
}
}
@IBAction func save(_ sender: Any) {
if let target = editTarget {
target.content = memo
DataManager.shared.saveContext()
} else {
DataManager.shared.addNewMemo(memo)
}
}
extension ComposeViewController {
static let newMemoDidInsert = Notification.Name(rawValue: "newMemoDidInsert")
static let memoDidChange = Notification.Name(rawValue: "memoDidChange")
}
if let target = editTarget {
target.content = memo
DataManager.shared.saveContext()
NotificationCenter.default.post(name: ComposeViewController.memoDidChange, object: nil)
} else {
DataManager.shared.addNewMemo(memo)
NotificationCenter.default.post(name: ComposeViewController.newMemoDidInsert, object: nil)
}
@IBOutlet weak var memoTableView: UITableView!
// 옵져버 해제
var token: NSObjectProtocol?
deinit {
if let token = token {
NotificationCenter.default.removeObserver(token)
}
}
override func viewDidLoad() {
super.viewDidLoad()
token = NotificationCenter.default.addObserver(forName: ComposeViewController.memoDidChange, object: nil, queue: OperationQueue.main, using: { [weak self] (noti) in
self?.memoTableView.reloadData()
})
}
}
Sheet를 풀다운할 때에 사용자에게 취소를 할 지, 안 할 지를 정하기!
// 편집 이전의 메모 내용을 저장하는 변수 생성
var originalMemoContent: String?
override func viewDidLoad() {
super.viewDidLoad()
if let memo = editTarget {
navigationItem.title = "메모 편집"
memoTextView.text = memo.content
originalMemoContent = memo.content
} else {
navigationItem.title = "새 메모"
memoTextView.text = ""
}
// 델리게이트 설정하기
memoTextView.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.presentationController?.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.presentationController?.delegate = nil
}
extension ComposeViewController: UITextViewDelegate {
// textView에서 text가 변경될 때마다 호출이 된다.
func textViewDidChange(_ textView: UITextView) {
if let original = originalMemoContent, let edited = textView.text {
// 원본과 편집된 것이 같은 지 다른지를 판단하여 편집이 된것인지 체크를 할 수 있다.
// 만약 다르다면(편집이 된 것이라면) isModalInPresentation -> true -> sheet를 내리는 것도 불가능하다.
isModalInPresentation = original != edited
}
}
}
extension ComposeViewController: UIAdaptivePresentationControllerDelegate {
// 만약 isModalInPresentation가 true라면 아래의 함수가 호출이 된다.
func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
// 경고 창 띄우기
let alert = UIAlertController(title: "알림", message: "편집한 내용을 저장할까요?", preferredStyle: .alert)
// 확인 액션 만들기
// 경고창에서 확인버튼을 누르면 클로져가 실행이 된다. -> save가 된다.
let okAction = UIAlertAction(title: "확인", style: .default) { [weak self] (action) in
self?.save(action)
}
alert.addAction(okAction)
// 취소 액션 만들기
// 경고창에서 취소버튼을 누르면 크로져가 실행이 된다.
let cancelAction = UIAlertAction(title: "취소", style: .cancel) { [weak self] (action) in
self?.close(action)
}
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
}
}
참고) 출처 - Zedd
https://zeddios.tistory.com/831
It's great to see a comprehensive breakdown of the process. By the way, if you're ever looking for additional resources or professional support for iOS app development, Cleveroad offers excellent services. Check them out at https://www.cleveroad.com/services/mobile-development/ios/.