티스토리 뷰
저장하지 않고 dismiss 할 때 ActionSheet 띄우기
UIAdaptivePresentationControllerDelegate
- UIAdaptivePresentationControllerDelegate
4개의 메서드가 있다.
func presentationControllerDidAttemptToDismiss(UIPresentationController)
: Notifies the delegate that a user-initiated attempt to dismiss a view was prevented.
func presentationControllerShouldDismiss(UIPresentationController) -> Bool
: Asks the delegate for permission to dismiss the presentation.
func presentationControllerDidDismiss(UIPresentationController)
: Notifies the delegate after a presentation is dismissed.
func presentationControllerWillDismiss(UIPresentationController)
: Notifies the delegate before a presentation is dismissed.
- presentationControllerDidAttemptToDismiss(_:)
dismiss 를 시도할 때 ActionSheet 를 띄울 것이기 때문에 이 메서드를 사용한다.
- UIKit 은
isModalInPresentation
이true
일 경우, dismiss 거부를 지원한다. 그래서 이 메서드를 사용해서UIAertController
인스턴스를 표시하는 등 dismiss 할 수 없는 이유를 사용자에게 알릴 수 있다.
isModalInPresentation
- isModalInPresentation
뷰컨이 modal behavior 를 적용하는지 여부를 나타내는 boolean 값이다. 즉, true
로 설정하면 interactive dismissal 를 막는 상태를 의미한다.
ActionSheet
presentationControllerDidAttemptToDismiss(_:) 로 ActionSheet 를 띄워보자.
뷰에서 변경사항이 없는대도 dismiss 를 거부하게되면 안되니까 hasChanges 라는 변수를 만들어서 여부를 설정하자.
//
override func viewWillLayoutSubviews() {
if #available(iOS 13.0, *) {
self.isModalInPresentation = self.hasChanges
} else {
//Fallback on earlier versions
}
}
뷰의 상태변화를 감지하기 위한 대표적인 메서드는 viewWillLayoutSubviews
와 viewDidLayoutSubViews
이다. 뷰가 바뀔 때마다 호출된다.
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.presentationController?.delegate = self
}
extension AddListViewController: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
if hasChanges {
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let dismiss = UIAlertAction(title: "변경 사항 폐기", style: .destructive) { _ in
//Hide keyboard
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)
}
}
문제
위의 코드를 따라갔는데 delegate 가 제대로 연결되지 않았는지 presentationControllerDidAttemptToDismiss
함수가 호출조차되지 않았다. 그래서 살펴보니 이 모달창은 navigationbar 의 push 가 아닌 modal present 였다. 코드 수정을 해주었다.
해결
self.presentationController?.delegate = self
로 델리게이트를 다시 연결해주었다. 나는 푸쉬로 네비게이션바에서 화면전환을 한 것이 아닌 스토리보드에서 modal 창을 띄워준 것이기 때문이다.
presentationController
current view controller 를 관리하는 것이 Presentation Controller 이다.
View Controller 가 Presentation Controller 에 의해서 관리되는 경우 이 프로퍼티는 해당 객체를 포함한다. 관리되지 않는 경우 이 속성은 nil 이다.
출처
출처ㅣhttps://developer.apple.com/documentation/uikit/uiviewcontroller/3229894-ismodalinpresentation/
출처ㅣhttps://developer.apple.com/documentation/uikit/uiadaptivepresentationcontrollerdelegate
출처ㅣhttps://zeddios.tistory.com/831?category=682195
출처ㅣhttps://developer.apple.com/documentation/uikit/uiviewcontroller/1621426-presentationcontroller
'iOS' 카테고리의 다른 글
iOS) UIButton 눌러도 반응하지 않도록 하기 (0) | 2021.07.20 |
---|---|
iOS) modal 창 뒤에 View 없애지 않기 (0) | 2021.07.20 |
iOS) UIAction 을 활용한 UIButton 에 핸들러 등록 (0) | 2021.07.20 |
iOS) Gesture Recognizer 를 활용한 화면전환 (0) | 2021.07.20 |
iOS) 다른 스토리보드로 화면전환 (0) | 2021.07.20 |
- Objective-C
- OpenSourceLibrary
- async/await
- YPImagePicker
- SwiftUI
- CloneCoding
- Widget
- watchOS
- WWDC22
- MVVM
- 2022 KAKAO TECH INTERNSHIP
- WWDC
- rxswift
- Swift
- Algorithm
- Notification
- containerBackground
- Protocol
- Firebase
- MOYA
- RxCocoa
- github
- configurable widget
- WidgetKit
- UserDefaults
- 서버통신
- IOS
- urlsession
- projectsetting
- APNS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Total
- Today
- Yesterday