diff --git a/example/ios/Podfile b/example/ios/Podfile index 7c6cb6f..5b51f56 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -27,6 +27,7 @@ def parse_KV_file(file, separator='=') end target 'Runner' do + use_frameworks! # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock # referring to absolute paths on developers' machines. system('rm -rf .symlinks') diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 721f7a7..2d1a726 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,5 +1,7 @@ PODS: + - BSImagePicker (3.1.3) - file_picker (0.0.1): + - BSImagePicker (~> 3.1.3) - Flutter - Flutter (1.0.0) - flutter_plugin_android_lifecycle (0.0.1): @@ -10,6 +12,10 @@ DEPENDENCIES: - Flutter (from `.symlinks/flutter/ios`) - flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`) +SPEC REPOS: + trunk: + - BSImagePicker + EXTERNAL SOURCES: file_picker: :path: ".symlinks/plugins/file_picker/ios" @@ -19,10 +25,11 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" SPEC CHECKSUMS: - file_picker: 408623be2125b79a4539cf703be3d4b3abe5e245 + BSImagePicker: 5798cfaadb386866b10d60bd1133065dc52cf273 + file_picker: 696824dae531ce6ed877fd8c1d145f006387c9fb Flutter: 0e3d915762c693b495b44d77113d4970485de6ec flutter_plugin_android_lifecycle: 47de533a02850f070f5696a623995e93eddcdb9b -PODFILE CHECKSUM: 1e5af4103afd21ca5ead147d7b81d06f494f51a2 +PODFILE CHECKSUM: 27341c1ab2a92ab24c1e60a397ab924b94c94ff5 COCOAPODS: 1.8.4 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 68cef48..085575b 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,13 +8,13 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 23AF7BA38BC7B93BD2287F6A /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E29C2B321AA1B6738D05DCC /* libPods-Runner.a */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + F4241881D42A79991D987032 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E093F13416E116B41F70DC9A /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -38,6 +38,7 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 92150FFEDED79AD7268B2247 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; @@ -47,9 +48,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9E29C2B321AA1B6738D05DCC /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - AA58896224B359D6BCEB4ED4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - D616774FB981784E6589DAC9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + A20269E5E72E5C7764E96D49 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + E093F13416E116B41F70DC9A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -57,7 +57,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 23AF7BA38BC7B93BD2287F6A /* libPods-Runner.a in Frameworks */, + F4241881D42A79991D987032 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -83,8 +83,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - EE3450EDCED914F636FA6BB9 /* Pods */, - BDC8FA085BD2993252DE5757 /* Frameworks */, + E62393F6B8A7F2BF56A0B62D /* Pods */, + EF8FB2B5878597859ACDA5F4 /* Frameworks */, ); sourceTree = ""; }; @@ -120,21 +120,21 @@ name = "Supporting Files"; sourceTree = ""; }; - BDC8FA085BD2993252DE5757 /* Frameworks */ = { + E62393F6B8A7F2BF56A0B62D /* Pods */ = { isa = PBXGroup; children = ( - 9E29C2B321AA1B6738D05DCC /* libPods-Runner.a */, + A20269E5E72E5C7764E96D49 /* Pods-Runner.debug.xcconfig */, + 92150FFEDED79AD7268B2247 /* Pods-Runner.release.xcconfig */, ); - name = Frameworks; + path = Pods; sourceTree = ""; }; - EE3450EDCED914F636FA6BB9 /* Pods */ = { + EF8FB2B5878597859ACDA5F4 /* Frameworks */ = { isa = PBXGroup; children = ( - D616774FB981784E6589DAC9 /* Pods-Runner.debug.xcconfig */, - AA58896224B359D6BCEB4ED4 /* Pods-Runner.release.xcconfig */, + E093F13416E116B41F70DC9A /* Pods_Runner.framework */, ); - name = Pods; + name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ @@ -144,14 +144,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - A3515840785C8A9829855BB5 /* [CP] Check Pods Manifest.lock */, + A43F367F477195F57487AEAA /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - AB4C7D1508951531E70F0A36 /* [CP] Embed Pods Frameworks */, + AE010F81F563ADC683AAAEBC /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -240,16 +240,20 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - A3515840785C8A9829855BB5 /* [CP] Check Pods Manifest.lock */ = { + A43F367F477195F57487AEAA /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); @@ -258,20 +262,26 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - AB4C7D1508951531E70F0A36 /* [CP] Embed Pods Frameworks */ = { + AE010F81F563ADC683AAAEBC /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 8; + buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/BSImagePicker/BSImagePicker.framework", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", + "${BUILT_PRODUCTS_DIR}/flutter_plugin_android_lifecycle/flutter_plugin_android_lifecycle.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BSImagePicker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_plugin_android_lifecycle.framework", ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; @@ -359,7 +369,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -409,7 +419,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -437,7 +447,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.mr.flutter.plugin.filepickerexampledemo; + PRODUCT_BUNDLE_IDENTIFIER = com.mr.flutter.plugin.filepickerdemo; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; @@ -464,7 +474,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.mr.flutter.plugin.filepickerexampledemo; + PRODUCT_BUNDLE_IDENTIFIER = com.mr.flutter.plugin.filepickerdemo; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; diff --git a/ios/Classes/FilePickerPlugin.m b/ios/Classes/FilePickerPlugin.m index 8c356f4..be35d32 100644 --- a/ios/Classes/FilePickerPlugin.m +++ b/ios/Classes/FilePickerPlugin.m @@ -2,6 +2,8 @@ #import "FileUtils.h" #import "ImageUtils.h" +@import BSImagePicker; + @interface FilePickerPlugin() @property (nonatomic) FlutterResult result; @property (nonatomic) UIViewController *viewController; @@ -47,7 +49,7 @@ _result = result; NSDictionary * arguments = call.arguments; BOOL isMultiplePick = ((NSNumber*)[arguments valueForKey:@"allowMultipleSelection"]).boolValue; - if(isMultiplePick || [call.method isEqualToString:@"ANY"] || [call.method containsString:@"CUSTOM"]) { + if((isMultiplePick && ![call.method isEqualToString:@"IMAGE"]) || [call.method isEqualToString:@"ANY"] || [call.method containsString:@"CUSTOM"]) { self.allowedExtensions = [FileUtils resolveType:call.method withAllowedExtensions: [arguments valueForKey:@"allowedExtensions"]]; if(self.allowedExtensions == nil) { _result([FlutterError errorWithCode:@"Unsupported file extension" @@ -62,7 +64,7 @@ } else if([call.method isEqualToString:@"AUDIO"]) { [self resolvePickAudio]; } else if([call.method isEqualToString:@"IMAGE"]) { - [self resolvePickImage]; + [self resolvePickImage:isMultiplePick]; } else { result(FlutterMethodNotImplemented); _result = nil; @@ -97,15 +99,56 @@ [_viewController presentViewController:self.documentPickerController animated:YES completion:nil]; } -- (void) resolvePickImage { +- (void) resolvePickImage:(BOOL)withMultiPick { - self.galleryPickerController = [[UIImagePickerController alloc] init]; - self.galleryPickerController.delegate = self; - self.galleryPickerController.modalPresentationStyle = UIModalPresentationCurrentContext; - self.galleryPickerController.mediaTypes = @[(NSString *)kUTTypeImage]; - self.galleryPickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; - - [_viewController presentViewController:self.galleryPickerController animated:YES completion:nil]; + if(!withMultiPick) { + self.galleryPickerController = [[UIImagePickerController alloc] init]; + self.galleryPickerController.delegate = self; + self.galleryPickerController.modalPresentationStyle = UIModalPresentationCurrentContext; + self.galleryPickerController.mediaTypes = @[(NSString *)kUTTypeImage]; + self.galleryPickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; + + [_viewController presentViewController:self.galleryPickerController animated:YES completion:nil]; + } else { + ImagePickerController * multiImagePickerController = [[ImagePickerController alloc] initWithSelectedAssets:@[]]; + + [_viewController presentImagePicker:multiImagePickerController + animated:YES + select:^(PHAsset * _Nonnull selectedAsset) {} + deselect:^(PHAsset * _Nonnull deselectedAsset) {} + cancel:^(NSArray * _Nonnull canceledAsset) {} + finish:^(NSArray * _Nonnull assets) { + NSMutableArray *paths = [[NSMutableArray alloc] init]; + + if(assets.count > 0) { + dispatch_semaphore_t completer = dispatch_semaphore_create(0); + __block int processedAssets = 0; + + for(PHAsset* asset in assets){ + [asset requestContentEditingInputWithOptions:[PHContentEditingInputRequestOptions new] completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) { + NSURL *imageURL = contentEditingInput.fullSizeImageURL; + [paths addObject:imageURL.path]; + + if(++processedAssets == assets.count) { + dispatch_semaphore_signal(completer); + } + }]; + } + + if (![NSThread isMainThread]) { + dispatch_semaphore_wait(completer, DISPATCH_TIME_FOREVER); + } else { + while (dispatch_semaphore_wait(completer, DISPATCH_TIME_NOW)) { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]]; + } + } + } + + self->_result(paths); + self->_result = nil; + + } completion:^{}]; + } } - (void) resolvePickAudio { diff --git a/ios/file_picker.podspec b/ios/file_picker.podspec index c6ad382..cc8cfce 100644 --- a/ios/file_picker.podspec +++ b/ios/file_picker.podspec @@ -15,7 +15,7 @@ A new flutter plugin project. s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - - s.ios.deployment_target = '8.0' + s.dependency 'BSImagePicker', '~> 3.1.3' + s.ios.deployment_target = '10.0' end