-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[image_picker] fixes for iOS which doesn't present camera/albums with more complex navigation #2755
[image_picker] fixes for iOS which doesn't present camera/albums with more complex navigation #2755
Conversation
…image or camera picker. Existing implementation is incorrect especially when adding project as a module with more complex presentation structure. If window's root view controller has presented modally any other view controller, it cannot present any other any more. Only the top most controller can present other. With this change, the image picker/camera controller is presented on the top most view controller.
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. ℹ️ Googlers: Go here for more info. |
d59a83b
to
9f58745
Compare
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. ℹ️ Googlers: Go here for more info. |
cc95b7d
to
d75a864
Compare
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
Contains code from the following PRs: flutter#2761 flutter#2755
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! It looks good overall. I left some comments.
- (UIImagePickerController *)getImagePickerController { | ||
return _imagePickerController; | ||
} | ||
|
||
- (UIViewController *)viewController { | ||
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is great! By the way, while we are here, can we also make it work for navigation controller? (pushed viewcontrollers)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also tab bar controller if possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this solution will work in this case as well.
According to the documentation you shouldn't push UIImagePickerController, but present it modally instead.
So in the situation that FlutterViewController is pushed into an existing navigation controller, e.g.:
Window
rootViewController
someOtherViewController
navigation controller (with some native view controller and FlutterVC)
image picker controller
not
Window
rootViewController
someOtherViewController
navigation controller (with some native view controller and FlutterVC, image picker controller)
I was worried about iPad which for a long time required popover presentation for albums, but since iOS 13 it presents modally as well without an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what i meant was that if topViewController is a view controller that is pushed in the navigation stack.
And we want to present the image picker controller on top of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cyanglaz the solution I made will work in virtually all cases, including these you are concerned about.
UINavigationController, UITabBarController they both manage internally some view controllers, but they themselves inherit from UIViewControllerr and either of them can be window's root view controller, or presented on some existing View Controller of any type.
The topViewController cannot be pushed in the navigation stack. In that case, UINavigationCoontroller is topViewController and some other push view controller is managed by UINavigationController. And with that arrangement, my solution will correctly display the Image Picker on top of the navigation controller.
Trust me - in my company we have already very complex navigation - some legacy Drawer Controller (in iOS), multiple Navigation controllers, TabBarControllers and Flutter V.C. is displayed on top of all of this. And my solution has been proven successful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
according to https://developer.apple.com/documentation/uikit/uiviewcontroller/1621407-presentedviewcontroller?language=objc the presentedViewController
is only the top view controller when it is presented with presentViewController:animated:completion:
.
What if the top view controller is presented by pushViewController? Does this still work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cyanglaz I am already repeating myself, but let me rephrase.
presentViewController
is a method of UIViewController
UINavigationController, UITabBarController, MySweetViewController - they are all subclasses of UIViewController, therefore they can be presented on any other view controller, or some other view controller can be presented on top of them.
The top view controller presented by push view controller - such a thing doesn't exist.
You can have UINavigationController either as a root of the window, or presented on some other view controller. And Navigation Controller manages the stack of view controllers. These view controllers shouldn't present any other view controller (because they are managed by NC). Instead, you either push another VC in NC (horizontal), or present VC on top of NC (vertical).
Moreover - if UINavigationController is one of the children of UITabBarController, you shouldn't present any VC on top of that NC, you should present on top of UITabBarController instead.
Some diagram
example1:
window
view controller 1
view controller 2
image picker
example2:
window
navigation controller (home, details)
image picker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I'm interested in this case you presented
example2:
window
navigation controller (home, details)
image picker
In this case, when you go through the code, what is the top view controller? Is it the navigation controller
?
And the image picker is going to use the navigation controller as the "viewController", regardless which view controller is the on the top of the stack of the navigation controller? Am I understanding correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exactly, image picker will be correctly presented on navigation controller. The contents of navigation controller doesn't matter at all.
@cyanglaz as requested changed version to 0.6.6+5 |
@cyanglaz any more feedback? I've already updated changelog a few times due to conflicts - other PRs being merged. |
@cyanglaz I have the same problem. |
@cyanglaz a gentle reminder for reviewing this PR, since this could be very useful to have. @chris-rutkowski looks like your branch has conflicts that need to be resolved before this can merge. Thank you in advance for this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Can we add tests for this?
window in normal circumstances is nil - in that case the key window will be found adds unit tests
@cyanglaz added unit test and improved the solution a bit. BTW I cannot find any guide to run iOS tests. I had to create a dummy project which wasn't very easy. |
@chris-rutkowski
|
@@ -7,7 +7,7 @@ | |||
@interface FLTImagePickerPlugin : NSObject <FlutterPlugin> | |||
|
|||
// For testing only. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we remove this line now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so? Both of these methods here are exposed only for testing and not meant to be used in normal circumstances.
… more complex navigation (flutter#2755)
… more complex navigation (flutter#2755)
… more complex navigation (flutter#2755)
Description
Existing implementation is incorrect especially when adding project as a module with more complex presentation structure.
If window's root view controller has presented modally any other view controller, it cannot present any other any more. Only the top most controller can present other.
With this change, the image picker/camera controller is presented on the top most view controller.
Related Issues
I found this issue raised by someone already:
flutter/flutter#34787
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]
). This will ensure a smooth and quick review process.///
).flutter analyze
) does not report any problems on my PR.Breaking Change
Does your PR require plugin users to manually update their apps to accommodate your change?