From 1b4648d0bb0681511ea3199bf87ed54dee695eec Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 23 Aug 2023 10:03:41 -0400 Subject: [PATCH 1/5] Eliminate nullable collection from Pigeon protocol --- .../image_picker_ios/lib/src/messages.g.dart | 9 +++++++-- .../image_picker/image_picker_ios/pigeons/messages.dart | 2 +- .../image_picker/image_picker_ios/test/test_api.g.dart | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/image_picker/image_picker_ios/lib/src/messages.g.dart b/packages/image_picker/image_picker_ios/lib/src/messages.g.dart index 91dde827a60..d9ce3624c88 100644 --- a/packages/image_picker/image_picker_ios/lib/src/messages.g.dart +++ b/packages/image_picker/image_picker_ios/lib/src/messages.g.dart @@ -179,7 +179,7 @@ class ImagePickerApi { } } - Future?> pickMultiImage(MaxSize arg_maxSize, + Future> pickMultiImage(MaxSize arg_maxSize, int? arg_imageQuality, bool arg_requestFullMetadata) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.ImagePickerApi.pickMultiImage', codec, @@ -198,8 +198,13 @@ class ImagePickerApi { message: replyList[1] as String?, details: replyList[2], ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); } else { - return (replyList[0] as List?)?.cast(); + return (replyList[0] as List?)!.cast(); } } diff --git a/packages/image_picker/image_picker_ios/pigeons/messages.dart b/packages/image_picker/image_picker_ios/pigeons/messages.dart index fb69a6d1334..be6b61a3fab 100644 --- a/packages/image_picker/image_picker_ios/pigeons/messages.dart +++ b/packages/image_picker/image_picker_ios/pigeons/messages.dart @@ -54,7 +54,7 @@ abstract class ImagePickerApi { int? imageQuality, bool requestFullMetadata); @async @ObjCSelector('pickMultiImageWithMaxSize:quality:fullMetadata:') - List? pickMultiImage( + List pickMultiImage( MaxSize maxSize, int? imageQuality, bool requestFullMetadata); @async @ObjCSelector('pickVideoWithSource:maxDuration:') diff --git a/packages/image_picker/image_picker_ios/test/test_api.g.dart b/packages/image_picker/image_picker_ios/test/test_api.g.dart index 6da0400b1a0..ca1a7af01ad 100644 --- a/packages/image_picker/image_picker_ios/test/test_api.g.dart +++ b/packages/image_picker/image_picker_ios/test/test_api.g.dart @@ -54,7 +54,7 @@ abstract class TestHostImagePickerApi { Future pickImage(SourceSpecification source, MaxSize maxSize, int? imageQuality, bool requestFullMetadata); - Future?> pickMultiImage( + Future> pickMultiImage( MaxSize maxSize, int? imageQuality, bool requestFullMetadata); Future pickVideo( @@ -117,7 +117,7 @@ abstract class TestHostImagePickerApi { final bool? arg_requestFullMetadata = (args[2] as bool?); assert(arg_requestFullMetadata != null, 'Argument for dev.flutter.pigeon.ImagePickerApi.pickMultiImage was null, expected non-null bool.'); - final List? output = await api.pickMultiImage( + final List output = await api.pickMultiImage( arg_maxSize!, arg_imageQuality, arg_requestFullMetadata!); return [output]; }); From 49880ae8b0b6a70cea2425792fb18cdf1b35bcea Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 23 Aug 2023 10:10:31 -0400 Subject: [PATCH 2/5] Update Dart accordingly --- .../lib/image_picker_ios.dart | 22 +++++++++---------- .../test/image_picker_ios_test.dart | 17 +++++++------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart index 02105f95e5a..4c302cae5f1 100644 --- a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart +++ b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart @@ -88,7 +88,7 @@ class ImagePickerIOS extends ImagePickerPlatform { double? maxHeight, int? imageQuality, }) async { - final List? paths = await _pickMultiImageAsPath( + final List paths = await _pickMultiImageAsPath( options: MultiImagePickerOptions( imageOptions: ImageOptions( maxWidth: maxWidth, @@ -97,7 +97,9 @@ class ImagePickerIOS extends ImagePickerPlatform { ), ), ); - if (paths == null) { + // Convert an empty list to a null return since that was the legacy behavior + // of this method. + if (paths.isEmpty) { return null; } @@ -108,15 +110,11 @@ class ImagePickerIOS extends ImagePickerPlatform { Future> getMultiImageWithOptions({ MultiImagePickerOptions options = const MultiImagePickerOptions(), }) async { - final List? paths = await _pickMultiImageAsPath(options: options); - if (paths == null) { - return []; - } - + final List paths = await _pickMultiImageAsPath(options: options); return paths.map((String path) => XFile(path)).toList(); } - Future?> _pickMultiImageAsPath({ + Future> _pickMultiImageAsPath({ MultiImagePickerOptions options = const MultiImagePickerOptions(), }) async { final int? imageQuality = options.imageOptions.imageQuality; @@ -141,7 +139,7 @@ class ImagePickerIOS extends ImagePickerPlatform { MaxSize(width: maxWidth, height: maxHeight), imageQuality, options.imageOptions.requestFullMetadata)) - ?.cast(); + .cast(); } Future _pickImageAsPath({ @@ -272,7 +270,7 @@ class ImagePickerIOS extends ImagePickerPlatform { double? maxHeight, int? imageQuality, }) async { - final List? paths = await _pickMultiImageAsPath( + final List paths = await _pickMultiImageAsPath( options: MultiImagePickerOptions( imageOptions: ImageOptions( maxWidth: maxWidth, @@ -281,7 +279,9 @@ class ImagePickerIOS extends ImagePickerPlatform { ), ), ); - if (paths == null) { + // Convert an empty list to a null return since that was the legacy behavior + // of this method. + if (paths.isEmpty) { return null; } diff --git a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart index da74e31f0a3..77fa322de6c 100644 --- a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart +++ b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart @@ -57,7 +57,7 @@ class _ApiLogger implements TestHostImagePickerApi { } @override - Future?> pickMultiImage( + Future> pickMultiImage( MaxSize maxSize, int? imageQuality, bool requestFullMetadata, @@ -68,7 +68,7 @@ class _ApiLogger implements TestHostImagePickerApi { 'imageQuality': imageQuality, 'requestFullMetadata': requestFullMetadata, })); - return returnValue as List?; + return returnValue as List; } @override @@ -441,8 +441,8 @@ void main() { ); }); - test('handles a null image path response gracefully', () async { - log.returnValue = null; + test('returns null for an empty list', () async { + log.returnValue = []; expect(await picker.pickMultiImage(), isNull); }); @@ -883,11 +883,10 @@ void main() { ); }); - test('handles a null image path response gracefully', () async { - log.returnValue = null; + test('returns null for an empty list', () async { + log.returnValue = []; expect(await picker.getMultiImage(), isNull); - expect(await picker.getMultiImage(), isNull); }); }); @@ -1643,8 +1642,8 @@ void main() { ); }); - test('handles a null image path response gracefully', () async { - log.returnValue = null; + test('handles an empty response', () async { + log.returnValue = []; expect(await picker.getMultiImageWithOptions(), isEmpty); }); From f6e7f6fd9f92297077e004311d6f5b0e0efbec67 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 23 Aug 2023 12:39:27 -0400 Subject: [PATCH 3/5] Update native side to never return nil list --- .../example/ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../ios/RunnerTests/ImagePickerPluginTests.m | 14 ++++++++++++++ .../ios/Classes/FLTImagePickerPlugin.m | 6 +++--- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj index 11c32e66da7..b609bcc60d1 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -345,7 +345,7 @@ isa = PBXProject; attributes = { DefaultBuildSystemTypeForWorkspace = Original; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 334733F12668136400DCC49E = { diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3504e681284..bca5e89903b 100755 --- a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ *_Nullable result, FlutterError *_Nullable error) { + XCTAssertEqualObjects(result, @[]); + [resultExpectation fulfill]; + }]; + [plugin sendCallResultWithSavedPathList:nil]; + + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + - (void)testPluginMediaPathHasItem { FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] init]; NSArray *pathList = @[ @"test" ]; diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m index c812e35186c..65120c4254d 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -173,7 +173,7 @@ - (void)pickImageWithSource:(nonnull FLTSourceSpecification *)source [self cancelInProgressCall]; FLTImagePickerMethodCallContext *context = [[FLTImagePickerMethodCallContext alloc] initWithResult:^void(NSArray *paths, FlutterError *error) { - if (paths && paths.count != 1) { + if (paths.count > 1) { completion(nil, [FlutterError errorWithCode:@"invalid_result" message:@"Incorrect number of return paths provided" details:nil]); @@ -246,7 +246,7 @@ - (void)pickVideoWithSource:(nonnull FLTSourceSpecification *)source (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { FLTImagePickerMethodCallContext *context = [[FLTImagePickerMethodCallContext alloc] initWithResult:^void(NSArray *paths, FlutterError *error) { - if (paths && paths.count != 1) { + if (paths.count > 1) { completion(nil, [FlutterError errorWithCode:@"invalid_result" message:@"Incorrect number of return paths provided" details:nil]); @@ -687,7 +687,7 @@ - (void)sendCallResultWithSavedPathList:(nullable NSArray *)pathList { message:@"pathList's items should not be null" details:nil]); } else { - self.callContext.result(pathList, nil); + self.callContext.result(pathList ?: [NSArray array], nil); } self.callContext = nil; } From 4570420842014c9697e22db61c9b915766337daf Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 23 Aug 2023 12:42:25 -0400 Subject: [PATCH 4/5] Version bump --- packages/image_picker/image_picker_ios/CHANGELOG.md | 3 ++- packages/image_picker/image_picker_ios/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index 81fcdb64ed0..c49ffbcb7c0 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 0.8.8+1 +* Fixes exception when canceling pickMultipleMedia. * Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. ## 0.8.8 diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index ac1b8e14d26..7c5a94f5b48 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: image_picker_ios description: iOS implementation of the image_picker plugin. repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.8 +version: 0.8.8+1 environment: sdk: ">=2.19.0 <4.0.0" From b557ff03f8951e338c752a609951fc4e919ed034 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 23 Aug 2023 12:46:12 -0400 Subject: [PATCH 5/5] Revert automatic project changes --- .../example/ios/Runner.xcodeproj/project.pbxproj | 2 +- .../ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj index b609bcc60d1..11c32e66da7 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -345,7 +345,7 @@ isa = PBXProject; attributes = { DefaultBuildSystemTypeForWorkspace = Original; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 334733F12668136400DCC49E = { diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index bca5e89903b..3504e681284 100755 --- a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@