[image_picker] fixes for iOS which doesn't present camera/albums with more complex navigation (#2755)
diff --git a/AUTHORS b/AUTHORS
index b27c156..17ede94 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -56,4 +56,5 @@
Ryo Miyake <ryo@miyake.id>
Théo Champion <contact.theochampion@gmail.com>
Kazuki Yamaguchi <y.kazuki0614n@gmail.com>
-Eitan Schwartz <eshvartz@gmail.com>
\ No newline at end of file
+Eitan Schwartz <eshvartz@gmail.com>
+Chris Rutkowski <chrisrutkowski89@gmail.com>
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index e3856c2..6b85f26 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.7+2
+
+* iOS: Fixes unpresentable album/image picker if window's root view controller is already presenting other view controller.
+
## 0.6.7+1
* Add web support to the example app.
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
index 38e5b56..b6d8687 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
@@ -7,7 +7,7 @@
@interface FLTImagePickerPlugin : NSObject <FlutterPlugin>
// For testing only.
-- (instancetype)initWithViewController:(UIViewController *)viewController;
- (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 4491575..00fdec2 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
@@ -25,7 +25,6 @@
@implementation FLTImagePickerPlugin {
NSDictionary *_arguments;
UIImagePickerController *_imagePickerController;
- UIViewController *_viewController;
UIImagePickerControllerCameraDevice _device;
}
@@ -33,25 +32,32 @@
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/image_picker"
binaryMessenger:[registrar messenger]];
- UIViewController *viewController =
- [UIApplication sharedApplication].delegate.window.rootViewController;
- FLTImagePickerPlugin *instance =
- [[FLTImagePickerPlugin alloc] initWithViewController:viewController];
+ FLTImagePickerPlugin *instance = [FLTImagePickerPlugin new];
[registrar addMethodCallDelegate:instance channel:channel];
}
-- (instancetype)initWithViewController:(UIViewController *)viewController {
- self = [super init];
- if (self) {
- _viewController = viewController;
- }
- return self;
-}
-
- (UIImagePickerController *)getImagePickerController {
return _imagePickerController;
}
+- (UIViewController *)viewControllerWithWindow:(UIWindow *)window {
+ UIWindow *windowToUse = window;
+ if (windowToUse == nil) {
+ for (UIWindow *window in [UIApplication sharedApplication].windows) {
+ if (window.isKeyWindow) {
+ windowToUse = window;
+ break;
+ }
+ }
+ }
+
+ UIViewController *topController = windowToUse.rootViewController;
+ while (topController.presentedViewController) {
+ topController = topController.presentedViewController;
+ }
+ return topController;
+}
+
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if (self.result) {
self.result([FlutterError errorWithCode:@"multiple_request"
@@ -136,7 +142,9 @@
[UIImagePickerController isCameraDeviceAvailable:_device]) {
_imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
_imagePickerController.cameraDevice = _device;
- [_viewController presentViewController:_imagePickerController animated:YES completion:nil];
+ [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
+ animated:YES
+ completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:@"Error"
message:@"Camera not available."
@@ -241,7 +249,9 @@
- (void)showPhotoLibrary {
// No need to check if SourceType is available. It always is.
_imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
- [_viewController presentViewController:_imagePickerController animated:YES completion:nil];
+ [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
+ animated:YES
+ completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker
diff --git a/packages/image_picker/image_picker/ios/Tests/ImagePickerPluginTests.m b/packages/image_picker/image_picker/ios/Tests/ImagePickerPluginTests.m
index e5c681e..c8d5a2b 100644
--- a/packages/image_picker/image_picker/ios/Tests/ImagePickerPluginTests.m
+++ b/packages/image_picker/image_picker/ios/Tests/ImagePickerPluginTests.m
@@ -7,6 +7,19 @@
@import image_picker;
@import XCTest;
+@interface MockViewController : UIViewController
+@property(nonatomic, retain) UIViewController *mockPresented;
+@end
+
+@implementation MockViewController
+@synthesize mockPresented;
+
+- (UIViewController *)presentedViewController {
+ return mockPresented;
+}
+
+@end
+
@interface FLTImagePickerPlugin (Test)
@property(copy, nonatomic) FlutterResult result;
- (void)handleSavedPath:(NSString *)path;
@@ -23,8 +36,7 @@
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
return;
}
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}];
@@ -39,8 +51,7 @@
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
return;
}
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
@@ -55,8 +66,7 @@
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
return;
}
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickVideo"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}];
@@ -71,8 +81,7 @@
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
return;
}
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
@@ -90,8 +99,7 @@
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
return;
}
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickVideo"
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}];
@@ -104,8 +112,7 @@
#pragma mark - Test video duration
- (void)testPickingVideoWithDuration {
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call = [FlutterMethodCall
methodCallWithMethodName:@"pickVideo"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0), @"maxDuration" : @95}];
@@ -116,8 +123,7 @@
}
- (void)testPluginPickImageSelectMultipleTimes {
- FLTImagePickerPlugin *plugin =
- [[FLTImagePickerPlugin alloc] initWithViewController:[UIViewController new]];
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
FlutterMethodCall *call =
[FlutterMethodCall methodCallWithMethodName:@"pickImage"
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}];
@@ -131,4 +137,16 @@
[plugin handleSavedPath:@"test"];
}
+- (void)testViewController {
+ UIWindow *window = [UIWindow new];
+ MockViewController *vc1 = [MockViewController new];
+ window.rootViewController = vc1;
+
+ UIViewController *vc2 = [UIViewController new];
+ vc1.mockPresented = vc2;
+
+ FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
+ XCTAssertEqual([plugin viewControllerWithWindow:window], vc2);
+}
+
@end
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index 9086028..4f52b19 100755
--- a/packages/image_picker/image_picker/pubspec.yaml
+++ b/packages/image_picker/image_picker/pubspec.yaml
@@ -2,7 +2,7 @@
description: Flutter plugin for selecting images from the Android and iOS image
library, and taking new pictures with the camera.
homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker
-version: 0.6.7+1
+version: 0.6.7+2
flutter:
plugin: