Search code examples
iosuiimagepickercontrollerios11

UIImagePickerController crashed with "[UIViewController _setCameraOverlayView:]: unrecognized selector" on iOS 11


I'm trying to create a customized UIImagePickerController with the following code. ECPhotoPickerController.h

@interface ECPhotoPickerController : UIImagePickerController
@property (strong, nonatomic) void(^didFinishSavingPhoto)(NSURL* url, UIImage* image);
@property (strong, nonatomic) void(^didDismissed)(void);
@end

ECPhotoPickerController.m

...
- (void)viewDidLoad {
    [super viewDidLoad];

    self.sourceType = UIImagePickerControllerSourceTypeCamera;
    self.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    self.showsCameraControls = false;

    [self setCameraOverlayView:self.overlayView];
    self.delegate = self;        
}
...

The customized image picker controller will be presented after I tapped a button, which would invoke the following method.

- (void)showImagePicker {

    ECPhotoPickerController* vc = [[ECPhotoPickerController alloc] init];
    vc.didFinishSavingPhoto = ^(NSURL *url, UIImage *image) {
        self.selectedImage = image;
    };
    vc.didDismissed = ^{
        // dismissed
    };
    [self presentViewController:vc animated:true completion:nil];
}

But the app will only crash on iOS 11 with the log

[UIViewController _setCameraOverlayView:]: unrecognized selector sent to instance 0x108403dd0

and there is anther weird log before the crash.

[] <<<< AVOutputDeviceDiscoverySession (FigRouteDiscoverer) >>>> -[AVFigRouteDiscovererOutputDeviceDiscoverySessionImpl outputDeviceDiscoverySessionDidChangeDiscoveryMode:]: Setting device discovery mode to DiscoveryMode_None (client: ECalligraphy)

The customized image picker class obviously inherit from UIImagePickerController.
And when I initialized it with [[ECPhotoPickerController alloc] init], it should invoke the super class's initialization since I didn't implement the initialization of ECPhotoPickerController.

I'm really confused about this crash. Any advice will be appreciated.


Solution

  • I final found the reason!
    The sourceType should be specified before the view controller start to be load on iOS 11.

    That means, you should set the value of sourceType during the initialization of your customized view controller or do it for the instance before load.

    - (instancetype)init { // `initFromNibName` etc. depends on the way you initialize it.
        if (self = [super init]) {
            self.sourceType = UIImagePickerControllerSourceTypeCamera;
            self.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
            self.showsCameraControls = false;
            self.delegate = self;
        }
        return self;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    

    Or

    - (void)showImagePicker {
        ECPhotoPickerController* vc = [[ECPhotoPickerController alloc] init];
        vc.sourceType = UIImagePickerControllerSourceTypeCamera;
        [self presentViewController:vc animated:true completion:nil];
    }