[image_picker] Default to gallery instead of camera when picking multiple images on pre-iOS 14 devices. (#4718)
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index 3dbf2c5..992c8b2 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.8.4+8
+
+* Configures the `UIImagePicker` to default to gallery instead of camera when
+picking multiple images on pre-iOS 14 devices.
+
## 0.8.4+7
* Refactors unit test to expose private interface via a separate test header instead of the inline declaration.
diff --git a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m
index bcaf2d1..5f32874 100644
--- a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m
+++ b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m
@@ -23,30 +23,26 @@
@end
@interface ImagePickerPluginTests : XCTestCase
-@property(readonly, nonatomic) id mockUIImagePicker;
-@property(readonly, nonatomic) id mockAVCaptureDevice;
+
@end
@implementation ImagePickerPluginTests
-- (void)setUp {
- _mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
- _mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]);
-}
-
- (void)testPluginPickImageDeviceBack {
+ id mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
+ id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]);
// UIImagePickerControllerSourceTypeCamera is supported
OCMStub(ClassMethod(
- [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
.andReturn(YES);
// UIImagePickerControllerCameraDeviceRear is supported
OCMStub(ClassMethod(
- [_mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]))
+ [mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]))
.andReturn(YES);
// AVAuthorizationStatusAuthorized is supported
- OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
.andReturn(AVAuthorizationStatusAuthorized);
// Run test
@@ -54,27 +50,30 @@
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}];
+ UIImagePickerController *controller = [[UIImagePickerController alloc] init];
+ [plugin setImagePickerControllerOverrides:@[ controller ]];
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
- XCTAssertEqual([plugin getImagePickerController].cameraDevice,
- UIImagePickerControllerCameraDeviceRear);
+ XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceRear);
}
- (void)testPluginPickImageDeviceFront {
+ id mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
+ id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]);
// UIImagePickerControllerSourceTypeCamera is supported
OCMStub(ClassMethod(
- [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
.andReturn(YES);
// UIImagePickerControllerCameraDeviceFront is supported
- OCMStub(ClassMethod([_mockUIImagePicker
- isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]))
+ OCMStub(ClassMethod(
+ [mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]))
.andReturn(YES);
// AVAuthorizationStatusAuthorized is supported
- OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
.andReturn(AVAuthorizationStatusAuthorized);
// Run test
@@ -82,27 +81,30 @@
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
+ UIImagePickerController *controller = [[UIImagePickerController alloc] init];
+ [plugin setImagePickerControllerOverrides:@[ controller ]];
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
- XCTAssertEqual([plugin getImagePickerController].cameraDevice,
- UIImagePickerControllerCameraDeviceFront);
+ XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceFront);
}
- (void)testPluginPickVideoDeviceBack {
+ id mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
+ id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]);
// UIImagePickerControllerSourceTypeCamera is supported
OCMStub(ClassMethod(
- [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
.andReturn(YES);
// UIImagePickerControllerCameraDeviceRear is supported
OCMStub(ClassMethod(
- [_mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]))
+ [mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]))
.andReturn(YES);
// AVAuthorizationStatusAuthorized is supported
- OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
.andReturn(AVAuthorizationStatusAuthorized);
// Run test
@@ -110,27 +112,31 @@
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickVideo"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}];
+ UIImagePickerController *controller = [[UIImagePickerController alloc] init];
+ [plugin setImagePickerControllerOverrides:@[ controller ]];
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
- XCTAssertEqual([plugin getImagePickerController].cameraDevice,
- UIImagePickerControllerCameraDeviceRear);
+ XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceRear);
}
- (void)testPluginPickVideoDeviceFront {
+ id mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
+ id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]);
+
// UIImagePickerControllerSourceTypeCamera is supported
OCMStub(ClassMethod(
- [_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
+ [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]))
.andReturn(YES);
// UIImagePickerControllerCameraDeviceFront is supported
- OCMStub(ClassMethod([_mockUIImagePicker
- isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]))
+ OCMStub(ClassMethod(
+ [mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]))
.andReturn(YES);
// AVAuthorizationStatusAuthorized is supported
- OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
+ OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
.andReturn(AVAuthorizationStatusAuthorized);
// Run test
@@ -138,12 +144,40 @@
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickVideo"
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
+ UIImagePickerController *controller = [[UIImagePickerController alloc] init];
+ [plugin setImagePickerControllerOverrides:@[ controller ]];
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
- XCTAssertEqual([plugin getImagePickerController].cameraDevice,
- UIImagePickerControllerCameraDeviceFront);
+ XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceFront);
+}
+
+- (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 {
+ if (@available(iOS 14, *)) {
+ return;
+ }
+
+ id mockUIImagePicker = OCMClassMock([UIImagePickerController class]);
+ id photoLibrary = OCMClassMock([PHPhotoLibrary class]);
+ OCMStub(ClassMethod([photoLibrary authorizationStatus]))
+ .andReturn(PHAuthorizationStatusAuthorized);
+
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
+ [plugin setImagePickerControllerOverrides:@[ mockUIImagePicker ]];
+ FlutterMethodCall *call = [FlutterMethodCall methodCallWithMethodName:@"pickMultiImage"
+ arguments:@{
+ @"maxWidth" : @(100),
+ @"maxHeight" : @(200),
+ @"imageQuality" : @(50),
+ }];
+
+ [plugin handleMethodCall:call
+ result:^(id _Nullable r){
+ }];
+
+ OCMVerify(times(1),
+ [mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]);
}
#pragma mark - Test camera devices, no op on simulators
@@ -156,15 +190,18 @@
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
+ UIImagePickerController *controller = [[UIImagePickerController alloc] init];
+ plugin.imagePickerControllerOverrides = @[ controller ];
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
plugin.result = ^(id result) {
};
+
// To ensure the flow does not crash by multiple cancel call
- [plugin imagePickerControllerDidCancel:[plugin getImagePickerController]];
- [plugin imagePickerControllerDidCancel:[plugin getImagePickerController]];
+ [plugin imagePickerControllerDidCancel:controller];
+ [plugin imagePickerControllerDidCancel:controller];
}
#pragma mark - Test video duration
@@ -174,10 +211,12 @@
FlutterMethodCall *call = [FlutterMethodCall
methodCallWithMethodName:@"pickVideo"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0), @"maxDuration" : @95}];
+ UIImagePickerController *controller = [[UIImagePickerController alloc] init];
+ [plugin setImagePickerControllerOverrides:@[ controller ]];
[plugin handleMethodCall:call
result:^(id _Nullable r){
}];
- XCTAssertEqual([plugin getImagePickerController].videoMaximumDuration, 95);
+ XCTAssertEqual(controller.videoMaximumDuration, 95);
}
- (void)testViewController {
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
index ffd23cd..c88db0b 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
@@ -8,7 +8,6 @@
@interface FLTImagePickerPlugin : NSObject <FlutterPlugin>
// For testing only.
-- (UIImagePickerController *)getImagePickerController;
- (UIViewController *)viewControllerWithWindow:(UIWindow *)window;
@end
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
index 1301398..cc841d6 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
@@ -31,12 +31,31 @@
PHPickerViewControllerDelegate,
UIAdaptivePresentationControllerDelegate>
+/**
+ * The maximum amount of images that are allowed to be picked.
+ */
@property(assign, nonatomic) int maxImagesAllowed;
+/**
+ * The arguments that are passed in from the Flutter method call.
+ */
@property(copy, nonatomic) NSDictionary *arguments;
+/**
+ * The PHPickerViewController instance used to pick multiple
+ * images.
+ */
@property(strong, nonatomic) PHPickerViewController *pickerViewController API_AVAILABLE(ios(14));
+/**
+ * The UIImagePickerController instances that will be used when a new
+ * controller would normally be created. Each call to
+ * createImagePickerController will remove the current first element from
+ * the array.
+ */
+@property(strong, nonatomic)
+ NSMutableArray<UIImagePickerController *> *imagePickerControllerOverrides;
+
@end
static const int SOURCE_CAMERA = 0;
@@ -44,9 +63,7 @@
typedef NS_ENUM(NSInteger, ImagePickerClassType) { UIImagePickerClassType, PHPickerClassType };
-@implementation FLTImagePickerPlugin {
- UIImagePickerController *_imagePickerController;
-}
+@implementation FLTImagePickerPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
@@ -56,8 +73,19 @@
[registrar addMethodCallDelegate:instance channel:channel];
}
-- (UIImagePickerController *)getImagePickerController {
- return _imagePickerController;
+- (UIImagePickerController *)createImagePickerController {
+ if ([self.imagePickerControllerOverrides count] > 0) {
+ UIImagePickerController *controller = [self.imagePickerControllerOverrides firstObject];
+ [self.imagePickerControllerOverrides removeObjectAtIndex:0];
+ return controller;
+ }
+
+ return [[UIImagePickerController alloc] init];
+}
+
+- (void)setImagePickerControllerOverrides:
+ (NSArray<UIImagePickerController *> *)imagePickerControllers {
+ _imagePickerControllerOverrides = [imagePickerControllers mutableCopy];
}
- (UIViewController *)viewControllerWithWindow:(UIWindow *)window {
@@ -88,7 +116,7 @@
* @param arguments that should be used to get cameraDevice value.
*/
- (UIImagePickerControllerCameraDevice)getCameraDeviceFromArguments:(NSDictionary *)arguments {
- NSInteger cameraDevice = [[arguments objectForKey:@"cameraDevice"] intValue];
+ NSInteger cameraDevice = [arguments[@"cameraDevice"] intValue];
return (cameraDevice == 1) ? UIImagePickerControllerCameraDeviceFront
: UIImagePickerControllerCameraDeviceRear;
}
@@ -108,22 +136,20 @@
[self checkPhotoAuthorizationForAccessLevel];
}
-- (void)pickImageWithUIImagePicker {
- _imagePickerController = [[UIImagePickerController alloc] init];
- _imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
- _imagePickerController.delegate = self;
- _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ];
-
- int imageSource = [[_arguments objectForKey:@"source"] intValue];
+- (void)launchUIImagePickerWithSource:(int)imageSource {
+ UIImagePickerController *imagePickerController = [self createImagePickerController];
+ imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
+ imagePickerController.delegate = self;
+ imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ];
self.maxImagesAllowed = 1;
switch (imageSource) {
case SOURCE_CAMERA:
- [self checkCameraAuthorization];
+ [self checkCameraAuthorizationWithImagePicker:imagePickerController];
break;
case SOURCE_GALLERY:
- [self checkPhotoAuthorization];
+ [self checkPhotoAuthorizationWithImagePicker:imagePickerController];
break;
default:
self.result([FlutterError errorWithCode:@"invalid_source"
@@ -141,10 +167,11 @@
self.result = nil;
}
+ self.result = result;
+ _arguments = call.arguments;
+
if ([@"pickImage" isEqualToString:call.method]) {
- self.result = result;
- _arguments = call.arguments;
- int imageSource = [[_arguments objectForKey:@"source"] intValue];
+ int imageSource = [call.arguments[@"source"] intValue];
if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker
if (@available(iOS 14, *)) {
@@ -152,44 +179,39 @@
[self pickImageWithPHPicker:1];
} else {
// UIImagePicker is used
- [self pickImageWithUIImagePicker];
+ [self launchUIImagePickerWithSource:imageSource];
}
} else {
- [self pickImageWithUIImagePicker];
+ [self launchUIImagePickerWithSource:imageSource];
}
} else if ([@"pickMultiImage" isEqualToString:call.method]) {
if (@available(iOS 14, *)) {
- self.result = result;
- _arguments = call.arguments;
[self pickImageWithPHPicker:0];
} else {
- [self pickImageWithUIImagePicker];
+ [self launchUIImagePickerWithSource:SOURCE_GALLERY];
}
} else if ([@"pickVideo" isEqualToString:call.method]) {
- _imagePickerController = [[UIImagePickerController alloc] init];
- _imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
- _imagePickerController.delegate = self;
- _imagePickerController.mediaTypes = @[
+ UIImagePickerController *imagePickerController = [self createImagePickerController];
+ imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
+ imagePickerController.delegate = self;
+ imagePickerController.mediaTypes = @[
(NSString *)kUTTypeMovie, (NSString *)kUTTypeAVIMovie, (NSString *)kUTTypeVideo,
(NSString *)kUTTypeMPEG4
];
- _imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
+ imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
- self.result = result;
- _arguments = call.arguments;
-
- int imageSource = [[_arguments objectForKey:@"source"] intValue];
- if ([[_arguments objectForKey:@"maxDuration"] isKindOfClass:[NSNumber class]]) {
- NSTimeInterval max = [[_arguments objectForKey:@"maxDuration"] doubleValue];
- _imagePickerController.videoMaximumDuration = max;
+ int imageSource = [call.arguments[@"source"] intValue];
+ if ([call.arguments[@"maxDuration"] isKindOfClass:[NSNumber class]]) {
+ NSTimeInterval max = [call.arguments[@"maxDuration"] doubleValue];
+ imagePickerController.videoMaximumDuration = max;
}
switch (imageSource) {
case SOURCE_CAMERA:
- [self checkCameraAuthorization];
+ [self checkCameraAuthorizationWithImagePicker:imagePickerController];
break;
case SOURCE_GALLERY:
- [self checkPhotoAuthorization];
+ [self checkPhotoAuthorizationWithImagePicker:imagePickerController];
break;
default:
result([FlutterError errorWithCode:@"invalid_source"
@@ -202,9 +224,9 @@
}
}
-- (void)showCamera {
+- (void)showCameraWithImagePicker:(UIImagePickerController *)imagePickerController {
@synchronized(self) {
- if (_imagePickerController.beingPresented) {
+ if (imagePickerController.beingPresented) {
return;
}
}
@@ -212,9 +234,9 @@
// Camera is not available on simulators
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] &&
[UIImagePickerController isCameraDeviceAvailable:device]) {
- _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
- _imagePickerController.cameraDevice = device;
- [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
+ imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
+ imagePickerController.cameraDevice = device;
+ [[self viewControllerWithWindow:nil] presentViewController:imagePickerController
animated:YES
completion:nil];
} else {
@@ -238,19 +260,19 @@
}
}
-- (void)checkCameraAuthorization {
+- (void)checkCameraAuthorizationWithImagePicker:(UIImagePickerController *)imagePickerController {
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (status) {
case AVAuthorizationStatusAuthorized:
- [self showCamera];
+ [self showCameraWithImagePicker:imagePickerController];
break;
case AVAuthorizationStatusNotDetermined: {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
- [self showCamera];
+ [self showCameraWithImagePicker:imagePickerController];
} else {
[self errorNoCameraAccess:AVAuthorizationStatusDenied];
}
@@ -266,14 +288,14 @@
}
}
-- (void)checkPhotoAuthorization {
+- (void)checkPhotoAuthorizationWithImagePicker:(UIImagePickerController *)imagePickerController {
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
switch (status) {
case PHAuthorizationStatusNotDetermined: {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if (status == PHAuthorizationStatusAuthorized) {
- [self showPhotoLibrary:UIImagePickerClassType];
+ [self showPhotoLibraryWithImagePicker:imagePickerController];
} else {
[self errorNoPhotoAccess:status];
}
@@ -282,7 +304,7 @@
break;
}
case PHAuthorizationStatusAuthorized:
- [self showPhotoLibrary:UIImagePickerClassType];
+ [self showPhotoLibraryWithImagePicker:imagePickerController];
break;
case PHAuthorizationStatusDenied:
case PHAuthorizationStatusRestricted:
@@ -301,9 +323,13 @@
handler:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if (status == PHAuthorizationStatusAuthorized) {
- [self showPhotoLibrary:PHPickerClassType];
+ [self
+ showPhotoLibraryWithPHPicker:self->
+ _pickerViewController];
} else if (status == PHAuthorizationStatusLimited) {
- [self showPhotoLibrary:PHPickerClassType];
+ [self
+ showPhotoLibraryWithPHPicker:self->
+ _pickerViewController];
} else {
[self errorNoPhotoAccess:status];
}
@@ -313,7 +339,7 @@
}
case PHAuthorizationStatusAuthorized:
case PHAuthorizationStatusLimited:
- [self showPhotoLibrary:PHPickerClassType];
+ [self showPhotoLibraryWithPHPicker:_pickerViewController];
break;
case PHAuthorizationStatusDenied:
case PHAuthorizationStatusRestricted:
@@ -355,21 +381,18 @@
}
}
-- (void)showPhotoLibrary:(ImagePickerClassType)imagePickerClassType {
- // No need to check if SourceType is available. It always is.
- switch (imagePickerClassType) {
- case PHPickerClassType:
- [[self viewControllerWithWindow:nil] presentViewController:_pickerViewController
- animated:YES
- completion:nil];
- break;
- case UIImagePickerClassType:
- _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
- [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
- animated:YES
- completion:nil];
- break;
- }
+- (void)showPhotoLibraryWithPHPicker:(PHPickerViewController *)pickerViewController
+ API_AVAILABLE(ios(14)) {
+ [[self viewControllerWithWindow:nil] presentViewController:pickerViewController
+ animated:YES
+ completion:nil];
+}
+
+- (void)showPhotoLibraryWithImagePicker:(UIImagePickerController *)imagePickerController {
+ imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
+ [[self viewControllerWithWindow:nil] presentViewController:imagePickerController
+ animated:YES
+ completion:nil];
}
- (NSNumber *)getDesiredImageQuality:(NSNumber *)imageQuality {
@@ -449,8 +472,8 @@
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info {
- NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
- [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
+ NSURL *videoURL = info[UIImagePickerControllerMediaURL];
+ [picker dismissViewControllerAnimated:YES completion:nil];
// The method dismissViewControllerAnimated does not immediately prevent
// further didFinishPickingMediaWithInfo invocations. A nil check is necessary
// to prevent below code to be unwantly executed multiple times and cause a
@@ -484,9 +507,9 @@
self.result = nil;
_arguments = nil;
} else {
- UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
+ UIImage *image = info[UIImagePickerControllerEditedImage];
if (image == nil) {
- image = [info objectForKey:UIImagePickerControllerOriginalImage];
+ image = info[UIImagePickerControllerOriginalImage];
}
NSNumber *maxWidth = GetNullableValueForKey(_arguments, @"maxWidth");
NSNumber *maxHeight = GetNullableValueForKey(_arguments, @"maxHeight");
@@ -523,7 +546,7 @@
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
- [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
+ [picker dismissViewControllerAnimated:YES completion:nil];
if (!self.result) {
return;
}
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin_Test.h b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin_Test.h
index 94eca42..5442f7d 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin_Test.h
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin_Test.h
@@ -40,4 +40,15 @@
*/
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
+/**
+ * Sets UIImagePickerController instances that will be used when a new
+ * controller would normally be created. Each call to
+ * createImagePickerController will remove the current first element from
+ * the array.
+ *
+ * Should be used for testing purposes only.
+ */
+- (void)setImagePickerControllerOverrides:
+ (NSArray<UIImagePickerController *> *)imagePickerControllers;
+
@end
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index 7142d82..43143f1 100755
--- a/packages/image_picker/image_picker/pubspec.yaml
+++ b/packages/image_picker/image_picker/pubspec.yaml
@@ -3,7 +3,7 @@
library, and taking new pictures with the camera.
repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
-version: 0.8.4+7
+version: 0.8.4+8
environment:
sdk: ">=2.14.0 <3.0.0"