UIImagePickerController 在 iOS 上因“[UIViewController _setCameraOverlayView:]: 无法识别的选择器”而崩溃 11

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

我正在尝试使用以下代码创建自定义 UIImagePickerControllerECPhotoPickerController.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;        
}
...

我点击一个按钮后,将显示自定义的图像选择器控制器,这将调用以下方法。

- (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];
}

但该应用程序 在 iOS 11 上崩溃,日志

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

并且在崩溃前还有一个奇怪的日志。

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

自定义图像选择器class显然继承自UIImagePickerController
当我用 [[ECPhotoPickerController alloc] init] 初始化它时,它应该调用超级 class 的初始化,因为我没有实现 ECPhotoPickerController.

的初始化

我对这次崩溃感到很困惑。 任何建议将不胜感激。

终于找到原因了!
应该在视图控制器开始之前指定sourceType 载入 iOS 11.

也就是说,您应该在自定义视图控制器的初始化期间设置 sourceType 的值,或者在加载之前为实例设置。

- (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];
}

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