[image_picker] Image picker phpicker impl (#3835)

* Add PHPicker libraries and its delegate

I have to implement PHPicker to select photos, live photos and videos from the photo library for iOS 14 and higher versions. But I also have to keep old UIImagePickerController for lower iOS versions and to use camera.

* Add PHPicker implementation

* Refactor UIImagePickerController implementation

I moved the UIImagePickerController implementation into pickImageWithUIImagePicker method for code reusability.

* Refactor handleMethodCall function

* Refactor showPhotoLibrary function

* Add the limited access into the photo library

I refactored the checkPhotoAuthorization function to add limited access functionality. Also I implemented showLimitedPhotoLibrary function to call presentLimitedLibraryPickerFromViewController.

* Add the implementation of picker function

I implemented picker function that is came from PHPickerViewControllerDelegate.

* Refactor Info.plist file

I added PHPhotoLibraryPreventAutomaticLimitedAccessAlert = YES into Info.plist to use limited access functionality.

* Add the function to get PHAssetResult

* Change the image to bypass HEIC problem

* Add UITest to test select photo functionality

* Add unit test for PHAssetResult

* Format the codes in all files

* Fix the unit test

* Update the version

* Add the description into CHANGELOG file

* Fix the license header

* Remove the unnecessary if statement

* Refactor PHPickerViewController to use property

* Refactor phPickerFlag state to use property

* Refactor the code to combine lines

* Refactor arguments to use property

* Revert formatting changes

This reverts part of commit 36b6a2aec20be6c76748f27a07d9f670d33a1313.

* Fix the unit test

* Format the code

* Refactor the UITest to skip lower versions

* Fix the property's name

* Refactor the properties to pass them via methods

* Add the getDesiredImageQuality method

* Add API_AVAILABLE for limited access method

* Refactor PHPickerController to use as a property

* Refactor PHPicker picker method and UITest

* Refactor the UITest

Move to UITest to new target file to test on iOS 14 and higher versions.

* Change the team to None  in the RunnerUITestiOS14

* Fix the UITest

* Refactor the method to fix dispatch

* Change to use self instead of weakSelf

* Fix the UITest to use XCTSkip

* Add ImagePickerClassType to use enum

* Remove unused method

If the user enabled limited library access, use presentLimitedLibraryPickerFromViewController to present the limited library picker so they may update their selection. But in this case, limited access status will not return with old requestAuthorization implementation in checkPhotoAuthorization method. So this method will not be used.

* Fix property to change copy to strong

* Refactor enum

* Change argument call

* Add checkPhotoAuthorizationForAccessLevel method

I implemented requestAuthorizationForAccessLevel which is the new way to handle the photo library authorization with iOS 14+.
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index 6af3cb0..58002a8 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.7.5
+
+* Fixes an issue where image rotation is wrong when Select Photos chose and image is scaled.
+* Breaking Changes:
+    * Migrate to PHPicker for iOS 14 and higher versions to pick image from the photo library.
+    * Implement the limited permission to pick photo from the photo library when Select Photo is chose.
+
 ## 0.7.4
 
 * Update flutter_plugin_android_lifecycle dependency to 2.0.1 to fix an R8 issue
diff --git a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
index f9895f0..4ea0e74 100644
--- a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj
@@ -10,7 +10,6 @@
 		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
 		5C9513011EC38BD300040975 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C9513001EC38BD300040975 /* GeneratedPluginRegistrant.m */; };
 		680049262280D736006DD6AB /* MetaDataUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 680049252280D736006DD6AB /* MetaDataUtilTests.m */; };
-		680049272280D79A006DD6AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
 		680049382280F2B9006DD6AB /* pngImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 680049352280F2B8006DD6AB /* pngImage.png */; };
 		680049392280F2B9006DD6AB /* jpgImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 680049362280F2B8006DD6AB /* jpgImage.jpg */; };
 		6801C8392555D726009DAF8D /* ImagePickerFromGalleryUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6801C8382555D726009DAF8D /* ImagePickerFromGalleryUITests.m */; };
@@ -23,6 +22,7 @@
 		9FC8F0E9229FA49E00C8D58F /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; };
 		9FC8F0EC229FA68500C8D58F /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; };
 		9FC8F0EE229FB90B00C8D58F /* ImageUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FC8F0ED229FB90B00C8D58F /* ImageUtilTests.m */; };
+		BE7AEE7926403CC8006181AA /* ImagePickerFromLimitedGalleryUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = BE7AEE7826403CC8006181AA /* ImagePickerFromLimitedGalleryUITests.m */; };
 		F4F7A436CCA4BF276270A3AE /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC32F6993F4529982D9519F1 /* libPods-Runner.a */; };
 		F78AF3192342D9D7008449C7 /* ImagePickerTestImages.m in Sources */ = {isa = PBXBuildFile; fileRef = F78AF3182342D9D7008449C7 /* ImagePickerTestImages.m */; };
 /* End PBXBuildFile section */
@@ -35,6 +35,13 @@
 			remoteGlobalIDString = 97C146ED1CF9000F007C117D;
 			remoteInfo = Runner;
 		};
+		BE7AEE7126403C46006181AA /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 97C146E61CF9000F007C117D /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 97C146ED1CF9000F007C117D;
+			remoteInfo = Runner;
+		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -80,6 +87,9 @@
 		9FC8F0E8229FA49E00C8D58F /* gifImage.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = gifImage.gif; sourceTree = "<group>"; };
 		9FC8F0ED229FB90B00C8D58F /* ImageUtilTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ImageUtilTests.m; path = ../../../ios/Tests/ImageUtilTests.m; sourceTree = "<group>"; };
 		A908FAEEA2A9B26D903C09C5 /* libPods-RunnerUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		BE7AEE6C26403C46006181AA /* RunnerUITestiOS14.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITestiOS14.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		BE7AEE7026403C46006181AA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		BE7AEE7826403CC8006181AA /* ImagePickerFromLimitedGalleryUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImagePickerFromLimitedGalleryUITests.m; sourceTree = "<group>"; };
 		EC32F6993F4529982D9519F1 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		F78AF3172342D9D7008449C7 /* ImagePickerTestImages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ImagePickerTestImages.h; path = ../../../ios/Tests/ImagePickerTestImages.h; sourceTree = "<group>"; };
 		F78AF3182342D9D7008449C7 /* ImagePickerTestImages.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ImagePickerTestImages.m; path = ../../../ios/Tests/ImagePickerTestImages.m; sourceTree = "<group>"; };
@@ -90,7 +100,6 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				F10E2DB84567A50A8721C9C7 /* libPods-RunnerUITests.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -102,6 +111,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		BE7AEE6926403C46006181AA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
@@ -159,6 +175,7 @@
 				9740EEB11CF90186004384FC /* Flutter */,
 				97C146F01CF9000F007C117D /* Runner */,
 				6801C8372555D726009DAF8D /* RunnerUITests */,
+				BE7AEE6D26403C46006181AA /* RunnerUITestiOS14 */,
 				97C146EF1CF9000F007C117D /* Products */,
 				840012C8B5EDBCF56B0E4AC1 /* Pods */,
 				CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
@@ -170,6 +187,7 @@
 			children = (
 				97C146EE1CF9000F007C117D /* Runner.app */,
 				6801C8362555D726009DAF8D /* RunnerUITests.xctest */,
+				BE7AEE6C26403C46006181AA /* RunnerUITestiOS14.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -198,6 +216,15 @@
 			name = "Supporting Files";
 			sourceTree = "<group>";
 		};
+		BE7AEE6D26403C46006181AA /* RunnerUITestiOS14 */ = {
+			isa = PBXGroup;
+			children = (
+				BE7AEE7826403CC8006181AA /* ImagePickerFromLimitedGalleryUITests.m */,
+				BE7AEE7026403C46006181AA /* Info.plist */,
+			);
+			path = RunnerUITestiOS14;
+			sourceTree = "<group>";
+		};
 		CF3B75C9A7D2FA2A4C99F110 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -250,6 +277,24 @@
 			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
 			productType = "com.apple.product-type.application";
 		};
+		BE7AEE6B26403C46006181AA /* RunnerUITestiOS14 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = BE7AEE7526403C46006181AA /* Build configuration list for PBXNativeTarget "RunnerUITestiOS14" */;
+			buildPhases = (
+				BE7AEE6826403C46006181AA /* Sources */,
+				BE7AEE6926403C46006181AA /* Frameworks */,
+				BE7AEE6A26403C46006181AA /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				BE7AEE7226403C46006181AA /* PBXTargetDependency */,
+			);
+			name = RunnerUITestiOS14;
+			productName = RunnerUITestiOS14;
+			productReference = BE7AEE6C26403C46006181AA /* RunnerUITestiOS14.xctest */;
+			productType = "com.apple.product-type.bundle.ui-testing";
+		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -273,6 +318,11 @@
 							};
 						};
 					};
+					BE7AEE6B26403C46006181AA = {
+						CreatedOnToolsVersion = 12.4;
+						ProvisioningStyle = Automatic;
+						TestTargetID = 97C146ED1CF9000F007C117D;
+					};
 				};
 			};
 			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
@@ -290,6 +340,7 @@
 			targets = (
 				97C146ED1CF9000F007C117D /* Runner */,
 				6801C8352555D726009DAF8D /* RunnerUITests */,
+				BE7AEE6B26403C46006181AA /* RunnerUITestiOS14 */,
 			);
 		};
 /* End PBXProject section */
@@ -316,6 +367,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		BE7AEE6A26403C46006181AA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
@@ -413,6 +471,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		BE7AEE6826403C46006181AA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				BE7AEE7926403CC8006181AA /* ImagePickerFromLimitedGalleryUITests.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
@@ -421,6 +487,11 @@
 			target = 97C146ED1CF9000F007C117D /* Runner */;
 			targetProxy = 6801C83B2555D726009DAF8D /* PBXContainerItemProxy */;
 		};
+		BE7AEE7226403C46006181AA /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 97C146ED1CF9000F007C117D /* Runner */;
+			targetProxy = BE7AEE7126403C46006181AA /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
@@ -642,6 +713,53 @@
 			};
 			name = Release;
 		};
+		BE7AEE7326403C46006181AA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = "";
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				INFOPLIST_FILE = RunnerUITestiOS14/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.baseflow.RunnerUITestiOS14;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				TEST_TARGET_NAME = Runner;
+			};
+			name = Debug;
+		};
+		BE7AEE7426403C46006181AA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = NHAKRD9N7D;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				INFOPLIST_FILE = RunnerUITestiOS14/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.baseflow.RunnerUITestiOS14;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				TEST_TARGET_NAME = Runner;
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
@@ -672,6 +790,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		BE7AEE7526403C46006181AA /* Build configuration list for PBXNativeTarget "RunnerUITestiOS14" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				BE7AEE7326403C46006181AA /* Debug */,
+				BE7AEE7426403C46006181AA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 97C146E61CF9000F007C117D /* Project object */;
diff --git a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 641cb8c..b1f7ff2 100755
--- a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1100"
+   LastUpgradeVersion = "1240"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -47,6 +47,16 @@
                ReferencedContainer = "container:Runner.xcodeproj">
             </BuildableReference>
          </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "BE7AEE6B26403C46006181AA"
+               BuildableName = "RunnerUITestiOS14.xctest"
+               BlueprintName = "RunnerUITestiOS14"
+               ReferencedContainer = "container:Runner.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
       </Testables>
    </TestAction>
    <LaunchAction
diff --git a/packages/image_picker/image_picker/example/ios/RunnerUITestiOS14/ImagePickerFromLimitedGalleryUITests.m b/packages/image_picker/image_picker/example/ios/RunnerUITestiOS14/ImagePickerFromLimitedGalleryUITests.m
new file mode 100644
index 0000000..86cad03
--- /dev/null
+++ b/packages/image_picker/image_picker/example/ios/RunnerUITestiOS14/ImagePickerFromLimitedGalleryUITests.m
@@ -0,0 +1,179 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <XCTest/XCTest.h>
+#import <os/log.h>
+
+const int kLimitedElementWaitingTime = 30;
+
+@interface ImagePickerFromLimitedGalleryUITests : XCTestCase
+
+@property(nonatomic, strong) XCUIApplication* app;
+
+@end
+
+@implementation ImagePickerFromLimitedGalleryUITests
+
+- (void)setUp {
+  [super setUp];
+  // Delete the app if already exists, to test permission popups
+
+  self.continueAfterFailure = NO;
+  self.app = [[XCUIApplication alloc] init];
+  [self.app launch];
+  __weak typeof(self) weakSelf = self;
+  [self addUIInterruptionMonitorWithDescription:@"Permission popups"
+                                        handler:^BOOL(XCUIElement* _Nonnull interruptingElement) {
+                                          if (@available(iOS 14, *)) {
+                                            XCUIElement* limitedPhotoPermission =
+                                                [interruptingElement.buttons elementBoundByIndex:0];
+                                            if (![limitedPhotoPermission
+                                                    waitForExistenceWithTimeout:
+                                                        kLimitedElementWaitingTime]) {
+                                              os_log_error(OS_LOG_DEFAULT, "%@",
+                                                           weakSelf.app.debugDescription);
+                                              XCTFail(@"Failed due to not able to find "
+                                                      @"selectPhotos butt   on with %@ seconds",
+                                                      @(kLimitedElementWaitingTime));
+                                            }
+                                            [limitedPhotoPermission tap];
+                                          } else {
+                                            XCUIElement* ok = interruptingElement.buttons[@"OK"];
+                                            if (![ok waitForExistenceWithTimeout:
+                                                         kLimitedElementWaitingTime]) {
+                                              os_log_error(OS_LOG_DEFAULT, "%@",
+                                                           weakSelf.app.debugDescription);
+                                              XCTFail(@"Failed due to not able to find ok button "
+                                                      @"with %@ seconds",
+                                                      @(kLimitedElementWaitingTime));
+                                            }
+                                            [ok tap];
+                                          }
+                                          return YES;
+                                        }];
+}
+
+- (void)tearDown {
+  [super tearDown];
+  [self.app terminate];
+}
+
+- (void)testSelectingFromGallery {
+  [self launchPickerAndSelect];
+}
+
+- (void)launchPickerAndSelect {
+  // Find and tap on the pick from gallery button.
+  NSPredicate* predicateToFindImageFromGalleryButton =
+      [NSPredicate predicateWithFormat:@"label == %@", @"image_picker_example_from_gallery"];
+
+  XCUIElement* imageFromGalleryButton =
+      [self.app.otherElements elementMatchingPredicate:predicateToFindImageFromGalleryButton];
+  if (![imageFromGalleryButton waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+    os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+    XCTFail(@"Failed due to not able to find image from gallery button with %@ seconds",
+            @(kLimitedElementWaitingTime));
+  }
+
+  XCTAssertTrue(imageFromGalleryButton.exists);
+  [imageFromGalleryButton tap];
+
+  // Find and tap on the `pick` button.
+  NSPredicate* predicateToFindPickButton =
+      [NSPredicate predicateWithFormat:@"label == %@", @"PICK"];
+
+  XCUIElement* pickButton = [self.app.buttons elementMatchingPredicate:predicateToFindPickButton];
+  if (![pickButton waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+    os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+    XCTSkip(@"Pick button isn't found so the test is skipped...");
+  }
+
+  XCTAssertTrue(pickButton.exists);
+  [pickButton tap];
+
+  // There is a known bug where the permission popups interruption won't get fired until a tap
+  // happened in the app. We expect a permission popup so we do a tap here.
+  [self.app tap];
+
+  // Find an image and tap on it. (IOS 14 UI, images are showing directly)
+  XCUIElement* aImage;
+  if (@available(iOS 14, *)) {
+    aImage = [self.app.scrollViews.firstMatch.images elementBoundByIndex:1];
+  } else {
+    XCUIElement* selectedPhotosCell = [self.app.cells
+        elementMatchingPredicate:[NSPredicate
+                                     predicateWithFormat:@"label == %@", @"Selected Photos"]];
+    if (![selectedPhotosCell waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+      os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+      XCTFail(@"Failed due to not able to find \"Selected Photos\" cell with %@ seconds",
+              @(kLimitedElementWaitingTime));
+    }
+    [selectedPhotosCell tap];
+    aImage = [self.app.collectionViews elementMatchingType:XCUIElementTypeCollectionView
+                                                identifier:@"PhotosGridView"]
+                 .cells.firstMatch;
+  }
+  os_log_error(OS_LOG_DEFAULT, "description before picking image %@", self.app.debugDescription);
+  if (![aImage waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+    os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+    XCTFail(@"Failed due to not able to find an image with %@ seconds",
+            @(kLimitedElementWaitingTime));
+  }
+  XCTAssertTrue(aImage.exists);
+  [aImage tap];
+
+  // Find and tap on the `Done` button.
+  NSPredicate* predicateToFindDoneButton =
+      [NSPredicate predicateWithFormat:@"label == %@", @"Done"];
+
+  XCUIElement* doneButton = [self.app.buttons elementMatchingPredicate:predicateToFindDoneButton];
+  if (![doneButton waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+    os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+    XCTSkip(@"Permissions popup could not fired so the test is skipped...");
+  }
+
+  XCTAssertTrue(doneButton.exists);
+  [doneButton tap];
+
+  // Find an image and tap on it to have access to selected photos.
+  if (@available(iOS 14, *)) {
+    aImage = [self.app.scrollViews.firstMatch.images elementBoundByIndex:1];
+  } else {
+    XCUIElement* selectedPhotosCell = [self.app.cells
+        elementMatchingPredicate:[NSPredicate
+                                     predicateWithFormat:@"label == %@", @"Selected Photos"]];
+    if (![selectedPhotosCell waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+      os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+      XCTFail(@"Failed due to not able to find \"Selected Photos\" cell with %@ seconds",
+              @(kLimitedElementWaitingTime));
+    }
+    [selectedPhotosCell tap];
+    aImage = [self.app.collectionViews elementMatchingType:XCUIElementTypeCollectionView
+                                                identifier:@"PhotosGridView"]
+                 .cells.firstMatch;
+  }
+  os_log_error(OS_LOG_DEFAULT, "description before picking image %@", self.app.debugDescription);
+  if (![aImage waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+    os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+    XCTFail(@"Failed due to not able to find an image with %@ seconds",
+            @(kLimitedElementWaitingTime));
+  }
+  XCTAssertTrue(aImage.exists);
+  [aImage tap];
+
+  // Find the picked image.
+  NSPredicate* predicateToFindPickedImage =
+      [NSPredicate predicateWithFormat:@"label == %@", @"image_picker_example_picked_image"];
+
+  XCUIElement* pickedImage = [self.app.images elementMatchingPredicate:predicateToFindPickedImage];
+  if (![pickedImage waitForExistenceWithTimeout:kLimitedElementWaitingTime]) {
+    os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription);
+    XCTFail(@"Failed due to not able to find pickedImage with %@ seconds",
+            @(kLimitedElementWaitingTime));
+  }
+
+  XCTAssertTrue(pickedImage.exists);
+}
+
+@end
diff --git a/packages/image_picker/image_picker/example/ios/RunnerUITestiOS14/Info.plist b/packages/image_picker/image_picker/example/ios/RunnerUITestiOS14/Info.plist
new file mode 100644
index 0000000..64d65ca
--- /dev/null
+++ b/packages/image_picker/image_picker/example/ios/RunnerUITestiOS14/Info.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/packages/image_picker/image_picker/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m b/packages/image_picker/image_picker/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m
index a3ca1a1..4b2163d 100644
--- a/packages/image_picker/image_picker/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m
+++ b/packages/image_picker/image_picker/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m
@@ -165,7 +165,7 @@
   // Find an image and tap on it. (IOS 14 UI, images are showing directly)
   XCUIElement* aImage;
   if (@available(iOS 14, *)) {
-    aImage = self.app.scrollViews.firstMatch.images.firstMatch;
+    aImage = [self.app.scrollViews.firstMatch.images elementBoundByIndex:1];
   } else {
     XCUIElement* allPhotosCell = [self.app.cells
         elementMatchingPredicate:[NSPredicate predicateWithFormat:@"label == %@", @"All Photos"]];
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h
index ce37ff7..0016765 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.h
@@ -4,6 +4,7 @@
 
 #import <Foundation/Foundation.h>
 #import <Photos/Photos.h>
+#import <PhotosUI/PhotosUI.h>
 
 #import "FLTImagePickerImageUtil.h"
 
@@ -13,6 +14,8 @@
 
 + (nullable PHAsset *)getAssetFromImagePickerInfo:(NSDictionary *)info;
 
++ (nullable PHAsset *)getAssetFromPHPickerResult:(PHPickerResult *)result API_AVAILABLE(ios(14));
+
 // Save image with correct meta data and extention copied from the original asset.
 // maxWidth and maxHeight are used only for GIF images.
 + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m
index caadc8b..51fc375 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m
@@ -23,6 +23,12 @@
   return result.firstObject;
 }
 
++ (PHAsset *)getAssetFromPHPickerResult:(PHPickerResult *)result API_AVAILABLE(ios(14)) {
+  PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[ result.assetIdentifier ]
+                                                                options:nil];
+  return fetchResult.firstObject;
+}
+
 + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData
                                        image:(UIImage *)image
                                     maxWidth:(NSNumber *)maxWidth
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
index 3b3551d..ffd23cd 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.h
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #import <Flutter/Flutter.h>
+#import <PhotosUI/PhotosUI.h>
 
 @interface FLTImagePickerPlugin : NSObject <FlutterPlugin>
 
diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
index 9159ea4..c368c42 100644
--- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
+++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m
@@ -7,23 +7,32 @@
 #import <AVFoundation/AVFoundation.h>
 #import <MobileCoreServices/MobileCoreServices.h>
 #import <Photos/Photos.h>
+#import <PhotosUI/PHPhotoLibrary+PhotosUISupport.h>
+#import <PhotosUI/PhotosUI.h>
 #import <UIKit/UIKit.h>
 
 #import "FLTImagePickerImageUtil.h"
 #import "FLTImagePickerMetaDataUtil.h"
 #import "FLTImagePickerPhotoAssetUtil.h"
 
-@interface FLTImagePickerPlugin () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
+@interface FLTImagePickerPlugin () <UINavigationControllerDelegate,
+                                    UIImagePickerControllerDelegate,
+                                    PHPickerViewControllerDelegate>
 
 @property(copy, nonatomic) FlutterResult result;
 
+@property(copy, nonatomic) NSDictionary *arguments;
+
+@property(strong, nonatomic) PHPickerViewController *pickerViewController API_AVAILABLE(ios(14));
+
 @end
 
 static const int SOURCE_CAMERA = 0;
 static const int SOURCE_GALLERY = 1;
 
+typedef NS_ENUM(NSInteger, ImagePickerClassType) { UIImagePickerClassType, PHPickerClassType };
+
 @implementation FLTImagePickerPlugin {
-  NSDictionary *_arguments;
   UIImagePickerController *_imagePickerController;
   UIImagePickerControllerCameraDevice _device;
 }
@@ -58,6 +67,47 @@
   return topController;
 }
 
+- (void)pickImageWithPHPicker:(bool)single API_AVAILABLE(ios(14)) {
+  PHPickerConfiguration *config =
+      [[PHPickerConfiguration alloc] initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary];
+  if (!single) {
+    config.selectionLimit = 0;  // Setting to zero allow us to pick unlimited photos
+  }
+  config.filter = [PHPickerFilter imagesFilter];
+
+  _pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:config];
+  _pickerViewController.delegate = self;
+
+  [self checkPhotoAuthorizationForAccessLevel];
+}
+
+- (void)pickImageWithUIImagePicker {
+  _imagePickerController = [[UIImagePickerController alloc] init];
+  _imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
+  _imagePickerController.delegate = self;
+  _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ];
+
+  int imageSource = [[_arguments objectForKey:@"source"] intValue];
+
+  switch (imageSource) {
+    case SOURCE_CAMERA: {
+      NSInteger cameraDevice = [[_arguments objectForKey:@"cameraDevice"] intValue];
+      _device = (cameraDevice == 1) ? UIImagePickerControllerCameraDeviceFront
+                                    : UIImagePickerControllerCameraDeviceRear;
+      [self checkCameraAuthorization];
+      break;
+    }
+    case SOURCE_GALLERY:
+      [self checkPhotoAuthorization];
+      break;
+    default:
+      self.result([FlutterError errorWithCode:@"invalid_source"
+                                      message:@"Invalid image source."
+                                      details:nil]);
+      break;
+  }
+}
+
 - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
   if (self.result) {
     self.result([FlutterError errorWithCode:@"multiple_request"
@@ -67,32 +117,26 @@
   }
 
   if ([@"pickImage" isEqualToString:call.method]) {
-    _imagePickerController = [[UIImagePickerController alloc] init];
-    _imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
-    _imagePickerController.delegate = self;
-    _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ];
-
     self.result = result;
     _arguments = call.arguments;
-
     int imageSource = [[_arguments objectForKey:@"source"] intValue];
 
-    switch (imageSource) {
-      case SOURCE_CAMERA: {
-        NSInteger cameraDevice = [[_arguments objectForKey:@"cameraDevice"] intValue];
-        _device = (cameraDevice == 1) ? UIImagePickerControllerCameraDeviceFront
-                                      : UIImagePickerControllerCameraDeviceRear;
-        [self checkCameraAuthorization];
-        break;
+    if (imageSource == SOURCE_GALLERY) {  // Capture is not possible with PHPicker
+      if (@available(iOS 14, *)) {
+        // PHPicker is used
+        [self pickImageWithPHPicker:true];
+      } else {
+        // UIImagePicker is used
+        [self pickImageWithUIImagePicker];
       }
-      case SOURCE_GALLERY:
-        [self checkPhotoAuthorization];
-        break;
-      default:
-        result([FlutterError errorWithCode:@"invalid_source"
-                                   message:@"Invalid image source."
-                                   details:nil]);
-        break;
+    } else {
+      [self pickImageWithUIImagePicker];
+    }
+  } else if ([@"pickMultiImage" isEqualToString:call.method]) {
+    if (@available(iOS 14, *)) {
+      self.result = result;
+      _arguments = call.arguments;
+      [self pickImageWithPHPicker:false];
     }
   } else if ([@"pickVideo" isEqualToString:call.method]) {
     _imagePickerController = [[UIImagePickerController alloc] init];
@@ -193,18 +237,49 @@
   switch (status) {
     case PHAuthorizationStatusNotDetermined: {
       [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
-        if (status == PHAuthorizationStatusAuthorized) {
-          dispatch_async(dispatch_get_main_queue(), ^{
-            [self showPhotoLibrary];
-          });
-        } else {
-          [self errorNoPhotoAccess:status];
-        }
+        dispatch_async(dispatch_get_main_queue(), ^{
+          if (status == PHAuthorizationStatusAuthorized) {
+            [self showPhotoLibrary:UIImagePickerClassType];
+          } else {
+            [self errorNoPhotoAccess:status];
+          }
+        });
       }];
       break;
     }
     case PHAuthorizationStatusAuthorized:
-      [self showPhotoLibrary];
+      [self showPhotoLibrary:UIImagePickerClassType];
+      break;
+    case PHAuthorizationStatusDenied:
+    case PHAuthorizationStatusRestricted:
+    default:
+      [self errorNoPhotoAccess:status];
+      break;
+  }
+}
+
+- (void)checkPhotoAuthorizationForAccessLevel API_AVAILABLE(ios(14)) {
+  PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
+  switch (status) {
+    case PHAuthorizationStatusNotDetermined: {
+      [PHPhotoLibrary
+          requestAuthorizationForAccessLevel:PHAccessLevelReadWrite
+                                     handler:^(PHAuthorizationStatus status) {
+                                       dispatch_async(dispatch_get_main_queue(), ^{
+                                         if (status == PHAuthorizationStatusAuthorized) {
+                                           [self showPhotoLibrary:PHPickerClassType];
+                                         } else if (status == PHAuthorizationStatusLimited) {
+                                           [self showPhotoLibrary:PHPickerClassType];
+                                         } else {
+                                           [self errorNoPhotoAccess:status];
+                                         }
+                                       });
+                                     }];
+      break;
+    }
+    case PHAuthorizationStatusAuthorized:
+    case PHAuthorizationStatusLimited:
+      [self showPhotoLibrary:PHPickerClassType];
       break;
     case PHAuthorizationStatusDenied:
     case PHAuthorizationStatusRestricted:
@@ -246,12 +321,86 @@
   }
 }
 
-- (void)showPhotoLibrary {
+- (void)showPhotoLibrary:(ImagePickerClassType)imagePickerClassType {
   // No need to check if SourceType is available. It always is.
-  _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
-  [[self viewControllerWithWindow:nil] presentViewController:_imagePickerController
-                                                    animated:YES
-                                                  completion:nil];
+  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;
+  }
+}
+
+- (NSNumber *)getDesiredImageQuality:(NSNumber *)imageQuality {
+  if (![imageQuality isKindOfClass:[NSNumber class]]) {
+    imageQuality = @1;
+  } else if (imageQuality.intValue < 0 || imageQuality.intValue > 100) {
+    imageQuality = [NSNumber numberWithInt:1];
+  } else {
+    imageQuality = @([imageQuality floatValue] / 100);
+  }
+  return imageQuality;
+}
+
+- (void)picker:(PHPickerViewController *)picker
+    didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)) {
+  [picker dismissViewControllerAnimated:YES completion:nil];
+
+  NSNumber *maxWidth = [_arguments objectForKey:@"maxWidth"];
+  NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"];
+  NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"];
+  NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality];
+
+  for (PHPickerResult *result in results) {
+    [result.itemProvider
+        loadObjectOfClass:[UIImage class]
+        completionHandler:^(__kindof id<NSItemProviderReading> _Nullable image,
+                            NSError *_Nullable error) {
+          if ([image isKindOfClass:[UIImage class]]) {
+            if (image != nil) {
+              __block UIImage *localImage = image;
+              dispatch_async(dispatch_get_main_queue(), ^{
+                if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
+                  localImage = [FLTImagePickerImageUtil scaledImage:localImage
+                                                           maxWidth:maxWidth
+                                                          maxHeight:maxHeight];
+                }
+
+                PHAsset *originalAsset =
+                    [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:result];
+
+                if (!originalAsset) {
+                  // Image picked without an original asset (e.g. User took a photo directly)
+                  [self saveImageWithPickerInfo:nil
+                                          image:localImage
+                                   imageQuality:desiredImageQuality];
+                } else {
+                  [[PHImageManager defaultManager]
+                      requestImageDataForAsset:originalAsset
+                                       options:nil
+                                 resultHandler:^(
+                                     NSData *_Nullable imageData, NSString *_Nullable dataUTI,
+                                     UIImageOrientation orientation, NSDictionary *_Nullable info) {
+                                   // maxWidth and maxHeight are used only for GIF images.
+                                   [self saveImageWithOriginalImageData:imageData
+                                                                  image:localImage
+                                                               maxWidth:maxWidth
+                                                              maxHeight:maxHeight
+                                                           imageQuality:desiredImageQuality];
+                                 }];
+                }
+              });
+            }
+          }
+        }];
+  }
 }
 
 - (void)imagePickerController:(UIImagePickerController *)picker
@@ -295,18 +444,10 @@
     if (image == nil) {
       image = [info objectForKey:UIImagePickerControllerOriginalImage];
     }
-
     NSNumber *maxWidth = [_arguments objectForKey:@"maxWidth"];
     NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"];
     NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"];
-
-    if (![imageQuality isKindOfClass:[NSNumber class]]) {
-      imageQuality = @1;
-    } else if (imageQuality.intValue < 0 || imageQuality.intValue > 100) {
-      imageQuality = [NSNumber numberWithInt:1];
-    } else {
-      imageQuality = @([imageQuality floatValue] / 100);
-    }
+    NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality];
 
     if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
       image = [FLTImagePickerImageUtil scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
@@ -315,20 +456,19 @@
     PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info];
     if (!originalAsset) {
       // Image picked without an original asset (e.g. User took a photo directly)
-      [self saveImageWithPickerInfo:info image:image imageQuality:imageQuality];
+      [self saveImageWithPickerInfo:info image:image imageQuality:desiredImageQuality];
     } else {
-      __weak typeof(self) weakSelf = self;
       [[PHImageManager defaultManager]
           requestImageDataForAsset:originalAsset
                            options:nil
                      resultHandler:^(NSData *_Nullable imageData, NSString *_Nullable dataUTI,
                                      UIImageOrientation orientation, NSDictionary *_Nullable info) {
                        // maxWidth and maxHeight are used only for GIF images.
-                       [weakSelf saveImageWithOriginalImageData:imageData
-                                                          image:image
-                                                       maxWidth:maxWidth
-                                                      maxHeight:maxHeight
-                                                   imageQuality:imageQuality];
+                       [self saveImageWithOriginalImageData:imageData
+                                                      image:image
+                                                   maxWidth:maxWidth
+                                                  maxHeight:maxHeight
+                                               imageQuality:desiredImageQuality];
                      }];
     }
   }
diff --git a/packages/image_picker/image_picker/ios/Tests/PhotoAssetUtilTests.m b/packages/image_picker/image_picker/ios/Tests/PhotoAssetUtilTests.m
index 2a1ba75..b81b29f 100644
--- a/packages/image_picker/image_picker/ios/Tests/PhotoAssetUtilTests.m
+++ b/packages/image_picker/image_picker/ios/Tests/PhotoAssetUtilTests.m
@@ -17,6 +17,18 @@
   XCTAssertNil([FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:mockData]);
 }
 
+- (void)testGetAssetFromPHPickerResultShouldReturnNilIfNotAvailable API_AVAILABLE(ios(14)) {
+  if (@available(iOS 14, *)) {
+    PHPickerResult *mockData;
+    [mockData.itemProvider
+        loadObjectOfClass:[UIImage class]
+        completionHandler:^(__kindof id<NSItemProviderReading> _Nullable image,
+                            NSError *_Nullable error) {
+          XCTAssertNil([FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:mockData]);
+        }];
+  }
+}
+
 - (void)testSaveImageWithOriginalImageData_ShouldSaveWithTheCorrectExtentionAndMetaData {
   // test jpg
   NSData *dataJPG = ImagePickerTestImages.JPGTestData;
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index e635128..4bc7cbe 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.7.4
+version: 0.7.5
 
 flutter:
   plugin: