Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[image_picker] Migrate iOS to Pigeon and improve state handling #5285

Merged
merged 10 commits into from
Apr 22, 2022
6 changes: 6 additions & 0 deletions packages/image_picker/image_picker_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.8.5

* Switches to an in-package method channel based on Pigeon.
* Fixes invalid casts when selecting multiple images on versions of iOS before
14.0.

## 0.8.4+11

* Splits from `image_picker` as a federated implementation.
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ - (void)testPluginPickImageDeviceBack {

// Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
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){
}];

[plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera
camera:FLTSourceCameraRear]
maxSize:[[FLTMaxSize alloc] init]
quality:nil
completion:^(NSString *_Nullable result, FlutterError *_Nullable error){
}];

XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceRear);
}
Expand All @@ -78,14 +79,15 @@ - (void)testPluginPickImageDeviceFront {

// Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
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){
}];

[plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera
camera:FLTSourceCameraFront]
maxSize:[[FLTMaxSize alloc] init]
quality:nil
completion:^(NSString *_Nullable result, FlutterError *_Nullable error){
}];

XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceFront);
}
Expand All @@ -109,14 +111,14 @@ - (void)testPluginPickVideoDeviceBack {

// Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
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){
}];

[plugin pickVideoWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera
camera:FLTSourceCameraRear]
maxDuration:nil
completion:^(NSString *_Nullable result, FlutterError *_Nullable error){
}];

XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceRear);
}
Expand All @@ -141,14 +143,14 @@ - (void)testPluginPickVideoDeviceFront {

// Run test
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
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){
}];

[plugin pickVideoWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera
camera:FLTSourceCameraFront]
maxDuration:nil
completion:^(NSString *_Nullable result, FlutterError *_Nullable error){
}];

XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceFront);
}
Expand All @@ -165,17 +167,12 @@ - (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 {

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){
}];

[plugin pickMultiImageWithMaxSize:[FLTMaxSize makeWithWidth:@(100) height:@(200)]
quality:@(50)
completion:^(NSArray<NSString *> *_Nullable result,
FlutterError *_Nullable error){
}];
OCMVerify(times(1),
[mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]);
}
Expand All @@ -187,17 +184,15 @@ - (void)testPluginPickImageDeviceCancelClickMultipleTimes {
return;
}
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
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) {

};
[plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera
camera:FLTSourceCameraRear]
maxSize:[[FLTMaxSize alloc] init]
quality:nil
completion:^(NSString *_Nullable result, FlutterError *_Nullable error){
}];

// To ensure the flow does not crash by multiple cancel call
[plugin imagePickerControllerDidCancel:controller];
Expand All @@ -208,14 +203,15 @@ - (void)testPluginPickImageDeviceCancelClickMultipleTimes {

- (void)testPickingVideoWithDuration {
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
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){
}];

[plugin pickVideoWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera
camera:FLTSourceCameraRear]
maxDuration:@(95)
completion:^(NSString *_Nullable result, FlutterError *_Nullable error){
}];

XCTAssertEqual(controller.videoMaximumDuration, 95);
}

Expand All @@ -231,37 +227,17 @@ - (void)testViewController {
XCTAssertEqual([plugin viewControllerWithWindow:window], vc2);
}

- (void)testPluginMultiImagePathIsNil {
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];

dispatch_semaphore_t resultSemaphore = dispatch_semaphore_create(0);
__block FlutterError *pickImageResult = nil;

plugin.result = ^(id _Nullable r) {
pickImageResult = r;
dispatch_semaphore_signal(resultSemaphore);
};
[plugin handleSavedPathList:nil];

dispatch_semaphore_wait(resultSemaphore, DISPATCH_TIME_FOREVER);

XCTAssertEqualObjects(pickImageResult.code, @"create_error");
}

- (void)testPluginMultiImagePathHasNullItem {
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
NSMutableArray *pathList = [NSMutableArray new];

[pathList addObject:[NSNull null]];

dispatch_semaphore_t resultSemaphore = dispatch_semaphore_create(0);
__block FlutterError *pickImageResult = nil;

plugin.result = ^(id _Nullable r) {
pickImageResult = r;
dispatch_semaphore_signal(resultSemaphore);
};
[plugin handleSavedPathList:pathList];
plugin.callContext = [[FLTImagePickerMethodCallContext alloc]
initWithResult:^(NSArray<NSString *> *_Nullable result, FlutterError *_Nullable error) {
pickImageResult = error;
dispatch_semaphore_signal(resultSemaphore);
}];
[plugin returnSavedPathList:@[ [NSNull null] ]];

dispatch_semaphore_wait(resultSemaphore, DISPATCH_TIME_FOREVER);

Expand All @@ -270,19 +246,17 @@ - (void)testPluginMultiImagePathHasNullItem {

- (void)testPluginMultiImagePathHasItem {
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new];
NSString *savedPath = @"test";
NSMutableArray *pathList = [NSMutableArray new];

[pathList addObject:savedPath];
NSArray *pathList = @[ @"test" ];

dispatch_semaphore_t resultSemaphore = dispatch_semaphore_create(0);
__block id pickImageResult = nil;

plugin.result = ^(id _Nullable r) {
pickImageResult = r;
dispatch_semaphore_signal(resultSemaphore);
};
[plugin handleSavedPathList:pathList];
plugin.callContext = [[FLTImagePickerMethodCallContext alloc]
initWithResult:^(NSArray<NSString *> *_Nullable result, FlutterError *_Nullable error) {
pickImageResult = result;
dispatch_semaphore_signal(resultSemaphore);
}];
[plugin returnSavedPathList:pathList];

dispatch_semaphore_wait(resultSemaphore, DISPATCH_TIME_FOREVER);

Expand Down
Loading