오잉?
아이폰에 있는 기본 미리알림(Reminder)앱을 클론코딩하던 중에 요상한 현상을 발견했습니다.
텍스트를 쓰던 도중, 저장을 안하고 pageSheet를 내렸을 때 actionSheet가 올라오는 현상이었죠.
🤔 그럼 이 기능을 어떻게 구현할 수 있을까?
UIAdaptivePresentationControllerDelegate에 있는 presentationControllerDidAttemptToDismiss함수를 사용해보자!
해당 Delegate는 presentation controller와 함께 app의 trait변화에 응답하는 방법을 결정하는 일련의 메소드들을 가지고 있어요.
해당 delegate 안에 있는 메소드들 중 하나가 presentationControllerDidAttemptToDismiss입니다.
네이밍에서도 알 수 있듯, 해당 메소드는 Dismiss를 시도했을 때 호출됩니다.
하지만, 그냥 바로 저 함수안에다가 ActionSheet를 present하게 한다고 해서 기능이 구현되는 건 아니에요.
그 전에 해줘야 하는 일들이 있습니다.
UIAdaptivePresentationControllerDelegate도 protocol이기에 우리가 delegate를 해줘야지만 그 안에 있는 메소드를 받아서 사용할 수 있어요.
isModalInPresentation를 true로 만들어줘야 합니다.
왜 true로 해줘야해요?
이 친구가 true여야만 DidAttemptToDismiss를 사용 가능해요.
일단 viewDidLoad안에다가 delegate와 isModalInPresentation를 기본 세팅해줍니다.
override func viewDidLoad() {
navigationController?.presentationController?.delegate = self
isModalInPresentation = true
}
저같은 경우에는 navigationController를 기반으로 한 viewController 위에서 사용하고 있기 때문에 navigationController에 있는 presentationController를 가지고 왔습니다.
현재 사용하시는 상황에 따라서 저 코드는 변경해주시면 됩니다.
그리고 Delegate를 가져와서 메소드 안을 채워줍시다.
extension NewAlertVC: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
if canSaved {
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let dismiss = UIAlertAction(title: "변경 사항 폐기", style: .destructive) { (_) in
self.resignFirstResponder()
self.dismiss(animated: true, completion: nil)
}
let cancel = UIAlertAction(title: "취소", style: .cancel, handler: nil)
alert.addAction(dismiss)
alert.addAction(cancel)
present(alert, animated: true, completion: nil)
} else {
dismiss(animated: true, completion: nil)
}
}
}
canSaved는 textField안에 text가 있는지 확인하는 변수를 제가 따로 만들어준겁니다.
save 가능한 상황에서 dismiss를 하는 경우에는 ActionSheet이 뜨는 걸 확인하실 수 있습니다.