From f0ba9fcf99fe687d05ea52792d3b8ad71c07c53f Mon Sep 17 00:00:00 2001 From: cjouannet Date: Mon, 20 Apr 2026 16:34:38 +0200 Subject: [PATCH] Add Swift Package Manager (SPM) support for iOS. Restructure iOS sources into SPM-compatible layout under ios/flutter_file_dialog/Sources/flutter_file_dialog/ with a Package.swift manifest. CocoaPods support is preserved via updated podspec pointing to the new source paths. Bump version to 3.1.0. --- CHANGELOG.md | 4 + ios/.gitignore | 1 + ios/Classes/FlutterFileDialogPlugin.h | 4 - ios/Classes/FlutterFileDialogPlugin.m | 8 -- ios/flutter_file_dialog.podspec | 19 +++-- ios/flutter_file_dialog/Package.swift | 17 ++++ .../FlutterFileDialogPlugin.swift} | 8 +- .../flutter_file_dialog}/OpenFileDialog.swift | 80 ++++++++----------- .../flutter_file_dialog}/SaveFileDialog.swift | 1 + .../Sources/flutter_file_dialog}/log.swift | 0 pubspec.yaml | 2 +- 11 files changed, 72 insertions(+), 72 deletions(-) delete mode 100644 ios/Classes/FlutterFileDialogPlugin.h delete mode 100644 ios/Classes/FlutterFileDialogPlugin.m create mode 100644 ios/flutter_file_dialog/Package.swift rename ios/{Classes/SwiftFlutterFileDialogPlugin.swift => flutter_file_dialog/Sources/flutter_file_dialog/FlutterFileDialogPlugin.swift} (95%) rename ios/{Classes => flutter_file_dialog/Sources/flutter_file_dialog}/OpenFileDialog.swift (77%) rename ios/{Classes => flutter_file_dialog/Sources/flutter_file_dialog}/SaveFileDialog.swift (99%) rename ios/{Classes => flutter_file_dialog/Sources/flutter_file_dialog}/log.swift (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70f2b2a..0b88cf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.0 + +- [iOS] Added Swift Package Manager (SPM) support alongside existing CocoaPods support + ## 3.0.3 - [Android] Updated compileSdkVersion to 36, Gradle to 8.14 and Java/Kotlin compatibility to version 17 diff --git a/ios/.gitignore b/ios/.gitignore index aa479fd..2107f27 100644 --- a/ios/.gitignore +++ b/ios/.gitignore @@ -9,6 +9,7 @@ profile DerivedData/ build/ +.build/ GeneratedPluginRegistrant.h GeneratedPluginRegistrant.m diff --git a/ios/Classes/FlutterFileDialogPlugin.h b/ios/Classes/FlutterFileDialogPlugin.h deleted file mode 100644 index ee8681d..0000000 --- a/ios/Classes/FlutterFileDialogPlugin.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface FlutterFileDialogPlugin : NSObject -@end diff --git a/ios/Classes/FlutterFileDialogPlugin.m b/ios/Classes/FlutterFileDialogPlugin.m deleted file mode 100644 index 7e7ad1b..0000000 --- a/ios/Classes/FlutterFileDialogPlugin.m +++ /dev/null @@ -1,8 +0,0 @@ -#import "FlutterFileDialogPlugin.h" -#import - -@implementation FlutterFileDialogPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftFlutterFileDialogPlugin registerWithRegistrar:registrar]; -} -@end diff --git a/ios/flutter_file_dialog.podspec b/ios/flutter_file_dialog.podspec index e46883a..a591d51 100644 --- a/ios/flutter_file_dialog.podspec +++ b/ios/flutter_file_dialog.podspec @@ -4,20 +4,19 @@ # Pod::Spec.new do |s| s.name = 'flutter_file_dialog' - s.version = '0.0.1' - s.summary = 'A new flutter plugin project.' + s.version = '3.1.0' + s.summary = 'Dialogs for picking and saving files in iOS.' s.description = <<-DESC -A new flutter plugin project. +A Flutter plugin providing dialogs for picking and saving files on iOS. DESC - s.homepage = 'http://example.com' + s.homepage = 'https://github.com/kineapps/flutter_file_dialog' s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } + s.author = { 'KineApps' => 'https://github.com/kineapps' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*' + s.source_files = 'flutter_file_dialog/Sources/flutter_file_dialog/**/*.swift' s.dependency 'Flutter' - s.platform = :ios, '10.0' + s.platform = :ios, '12.0' - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.9' end diff --git a/ios/flutter_file_dialog/Package.swift b/ios/flutter_file_dialog/Package.swift new file mode 100644 index 0000000..41eb769 --- /dev/null +++ b/ios/flutter_file_dialog/Package.swift @@ -0,0 +1,17 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "flutter_file_dialog", + platforms: [ + .iOS(.v12) + ], + products: [ + .library(name: "flutter-file-dialog", targets: ["flutter_file_dialog"]) + ], + targets: [ + .target( + name: "flutter_file_dialog" + ) + ] +) diff --git a/ios/Classes/SwiftFlutterFileDialogPlugin.swift b/ios/flutter_file_dialog/Sources/flutter_file_dialog/FlutterFileDialogPlugin.swift similarity index 95% rename from ios/Classes/SwiftFlutterFileDialogPlugin.swift rename to ios/flutter_file_dialog/Sources/flutter_file_dialog/FlutterFileDialogPlugin.swift index 657da40..f1c97cd 100644 --- a/ios/Classes/SwiftFlutterFileDialogPlugin.swift +++ b/ios/flutter_file_dialog/Sources/flutter_file_dialog/FlutterFileDialogPlugin.swift @@ -6,15 +6,15 @@ import Flutter import UIKit -public class SwiftFlutterFileDialogPlugin: NSObject, FlutterPlugin { +public class FlutterFileDialogPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "flutter_file_dialog", binaryMessenger: registrar.messenger()) - let instance = SwiftFlutterFileDialogPlugin() + let instance = FlutterFileDialogPlugin() registrar.addMethodCallDelegate(instance, channel: channel) } deinit { - writeLog("SwiftFlutterFileDialogPlugin.deinit") + writeLog("FlutterFileDialogPlugin.deinit") } var openFileDialog: OpenFileDialog? @@ -82,7 +82,7 @@ struct OpenFileDialogParams { default: sourceType = .photoLibrary } - + allowEditing = data["allowEditing"] as? Bool ?? false allowedUtiTypes = data["allowedUtiTypes"] as? [String] diff --git a/ios/Classes/OpenFileDialog.swift b/ios/flutter_file_dialog/Sources/flutter_file_dialog/OpenFileDialog.swift similarity index 77% rename from ios/Classes/OpenFileDialog.swift rename to ios/flutter_file_dialog/Sources/flutter_file_dialog/OpenFileDialog.swift index 9b4fb89..a4501c0 100644 --- a/ios/Classes/OpenFileDialog.swift +++ b/ios/flutter_file_dialog/Sources/flutter_file_dialog/OpenFileDialog.swift @@ -3,6 +3,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. +import Flutter import Foundation import MobileCoreServices import UIKit @@ -106,54 +107,43 @@ class OpenFileDialog: NSObject, UIDocumentPickerDelegate, UIImagePickerControlle func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { picker.dismiss(animated: true, completion: nil) - if #available(iOS 11.0, *) { - if !params!.allowEditing, let pickedFileUrl: URL = info[UIImagePickerController.InfoKey.imageURL] as? URL { - writeLog("picked file: " + pickedFileUrl.absoluteString) - handlePickedFile(pickedFileUrl) - } else { - if let pickedImage: UIImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage ?? - info[UIImagePickerController.InfoKey.originalImage] as? UIImage - { - // save picked image to temp dir - DispatchQueue.global(qos: .userInitiated).async { - do { - let directory = NSTemporaryDirectory() - - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyyMMddHHmmss" - - let fileName = dateFormatter.string(from: Date()) + ".jpg" - - let destinationFileUrl = NSURL.fileURL(withPathComponents: [directory, fileName])! - - let jpeg = pickedImage.jpegData(compressionQuality: CGFloat(1.0))! - try jpeg.write(to: destinationFileUrl) - - // return picked file path - DispatchQueue.main.async { - writeLog("Saved picked image to: " + destinationFileUrl.path) - self.flutterResult?(destinationFileUrl.path) - } - } catch { - DispatchQueue.main.async { - writeLog(error.localizedDescription) - self.flutterResult?(FlutterError(code: "file_copy_error", - message: error.localizedDescription, - details: nil)) - } + if !params!.allowEditing, let pickedFileUrl: URL = info[UIImagePickerController.InfoKey.imageURL] as? URL { + writeLog("picked file: " + pickedFileUrl.absoluteString) + handlePickedFile(pickedFileUrl) + } else { + if let pickedImage: UIImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage ?? + info[UIImagePickerController.InfoKey.originalImage] as? UIImage + { + // save picked image to temp dir + DispatchQueue.global(qos: .userInitiated).async { + do { + let directory = NSTemporaryDirectory() + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyyMMddHHmmss" + + let fileName = dateFormatter.string(from: Date()) + ".jpg" + + let destinationFileUrl = NSURL.fileURL(withPathComponents: [directory, fileName])! + + let jpeg = pickedImage.jpegData(compressionQuality: CGFloat(1.0))! + try jpeg.write(to: destinationFileUrl) + + DispatchQueue.main.async { + writeLog("Saved picked image to: " + destinationFileUrl.path) + self.flutterResult?(destinationFileUrl.path) + } + } catch { + DispatchQueue.main.async { + writeLog(error.localizedDescription) + self.flutterResult?(FlutterError(code: "file_copy_error", + message: error.localizedDescription, + details: nil)) } } - } else { - flutterResult?(nil) } - } - } else { - // Fallback on earlier versions - DispatchQueue.main.async { - writeLog("iOS 11 or higher required") - self.flutterResult?(FlutterError(code: "minimum_target", - message: "iOS 11 or higher required", - details: nil)) + } else { + flutterResult?(nil) } } } diff --git a/ios/Classes/SaveFileDialog.swift b/ios/flutter_file_dialog/Sources/flutter_file_dialog/SaveFileDialog.swift similarity index 99% rename from ios/Classes/SaveFileDialog.swift rename to ios/flutter_file_dialog/Sources/flutter_file_dialog/SaveFileDialog.swift index c23d369..4d52b54 100644 --- a/ios/Classes/SaveFileDialog.swift +++ b/ios/flutter_file_dialog/Sources/flutter_file_dialog/SaveFileDialog.swift @@ -3,6 +3,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. +import Flutter import Foundation import UIKit diff --git a/ios/Classes/log.swift b/ios/flutter_file_dialog/Sources/flutter_file_dialog/log.swift similarity index 100% rename from ios/Classes/log.swift rename to ios/flutter_file_dialog/Sources/flutter_file_dialog/log.swift diff --git a/pubspec.yaml b/pubspec.yaml index 7619bc2..7db7ec8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_file_dialog description: Dialogs for picking and saving files in Android and in iOS. -version: 3.0.3 +version: 3.1.0 homepage: https://github.com/kineapps/flutter_file_dialog repository: https://github.com/kineapps/flutter_file_dialog