I'm trying to detect when the imagePickerController via swipe is closed via swipe-down gesture or via cancel.
The imagePicker is loaded via this method (https://developer.apple.com/documentation/uikit/uiviewcontroller/1621380-presentviewcontroller)
[rootViewController presentViewController:picker animated:animated completion:NULL];
and we can simply detect if the pickerController is closed via cancel by implementing this method (https://developer.apple.com/documentation/uikit/uiimagepickercontrollerdelegate/1619133-imagepickercontrollerdidcancel)
however, I also want to detect if it is closed via swipe down (for iPhone X, ..., we can swipe down to close a view that is show modally)
with Swift, I can detect it with this code:
extension UIImagePickerController {
open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// detecting
}
}
I wonder if the is an equivalent way to do this in objective C (since the project I'm working on is written in objective C)? or any other suggestion is welcomed :D
First of all, you should not override viewDidDisappear:
in an extension in Swift (nor in a category in Objective-C). The result of overriding something in an extension/category is undefined behavior - it may work, it may not. It should never be relied upon.
Instead, assign the delegate of your image picker's presentationController
to some class, then have that class implement the presentationControllerDidDismiss:
method. This method is called when the user has taken action to dismiss the image picker successfully, after all animations are finished. (And note that it's not called if the image picker is dismissed programatically.)
Here's a short example that covers all the cases of dismissing your image picker without the need to override viewDidDisappear:
in an extension or category:
@interface ViewController() <UIAdaptivePresentationControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@end
@implementation ViewController
- (IBAction)showImagePicker {
UIImagePickerController *imagePicker = [UIImagePickerController new];
imagePicker.delegate = self;
imagePicker.presentationController.delegate = self;
[self presentViewController:imagePicker animated:YES completion:nil];
}
#pragma mark - UIAdaptivePresentationControllerDelegate
- (void)presentationControllerWillDismiss:(UIPresentationController *)presentationController {
NSLog(@"The user began to swipe down to dismiss.");
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController {
NSLog(@"The dismissal animation finished after the user swiped down.");
// This is probably where you want to put your code that you want to call.
}
#pragma mark - UIImagePickerControllerDelegate, UINavigationControllerDelegate
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
NSLog(@"The user tapped the image picker's Cancel button.");
[self dismissViewControllerAnimated:YES completion:^{
NSLog(@"The dismissal animation finished after the user tapped Cancel.");
}];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey, id> *)info {
NSLog(@"The user selected an image from the image picker.");
[self dismissViewControllerAnimated:YES completion:^{
NSLog(@"The dismissal animation finished after the user selected an image.");
}];
}
@end
And here's a Swift version for good measure:
class ViewController: UIViewController {
@IBAction func showImagePicker() {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.presentationController?.delegate = self
present(imagePicker, animated: true)
}
}
extension ViewController: UIAdaptivePresentationControllerDelegate {
func presentationControllerWillDismiss(_ presentationController: UIPresentationController) {
print("The user began to swipe down to dismiss.")
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
print("The dismissal animation finished after the user swiped down.")
// This is probably where you want to put your code that you want to call.
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("The user tapped the image picker's Cancel button.")
dismiss(animated: true) {
print("The dismissal animation finished after the user tapped Cancel.")
}
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
print("The user selected an image from the image picker.")
dismiss(animated: true){
print("The dismissal animation finished after the user selected an image.")
}
}
}