作者:质数心情
链接:https://juejin.cn/post/6908232699673722888

目的: 实现一个flutter调用原生ios相册的功能,并传递照片

flutter的操作

flutter用来传递的模块叫channel,这里我们使用MethodChannel

// 注册通道

MethodChannel _methodChannel = MethodChannel("picture_page");

// 发送消息

_methodChannel.invokeMapMethod("picture");

// 接收消息

_methodChannel.setMethodCallHandler((call) async {
      if (call.method == "picture-ios") {
        print("ios call arguments --- " + call.arguments);
      }
    });

iOS的操作

iOS端用来传递的模块是FlutterMethodChannel

//注册通道

methodChannel = FlutterMethodChannel(name: "picture_page", binaryMessenger: vc as! FlutterBinaryMessenger)

// 发送消息

self?.methodChannel.invokeMethod("picture-ios", arguments: "img")

//接收消息

methodChannel.setMethodCallHandler { (call, result) in
        if call.method == "picture" {
            print("call method - ", call.method)
        }
    }

调用相册

在iOS14后苹果推荐使用新的PHPicker来代替UIImagePicker,使用PHPicker需要先导入框架PhotosUI

photosUI包含

* PHPickerConfiguration
* PHPickerFilter
* PHPickerResult
* PHPickerViewController
* PHPickerViewControllerDelegate

PHPickerConfiguration 配置类

* selectionLimit: 最多可以选择几张照片,0是多张,默认是1
* preferredAssetRepresentationMode: 用来指定导出结果的表示形式,默认值是 automatic, 此时系统会自动执行一些转码之类的操作
* filter: PHPickerFilter, 筛选模式,可以指定筛选照片,视频,livephoto

PHPickerViewController 选择器

* delegate: 代理,只有一个代理方法了!! 用户完成选择后,该方***触发,用户选择的结果会以 PHPickerResult 数组的形式传入,每一个 PHPickerResult 都对应一个照片、视频或者 LivePhoto 的数据

PHPickerResult 照片信息

* itemProvider: NSItemProvider, 通过 itemProvider 的 api,我们可以获取到最终的结果
* assetIdentifier: 选中对象对应的PHAsset的id, 如果要访问PHAsset的额外信息,需要获取到相册权限后才可以执行

获取照片

    // 获取到图片
    itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
        // do someting with results
    }
    
    // 获取到图片地址, 这个 api 返回的是一个 URL 类型的临时文件路径,苹果在这个 API 的说明中指出:系统会把请求的文件数据复制到这个路径对应的地址,并且在回调执行完毕后删除临时文件。
    itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.image.identifier) { (url, error) in
    }

iOS14的PHPicker获取到的图片地址是临时路径,所以使用UIImagePickerViewController获取到的在tmp路径下的地址会更方便一些.
或者将PHPicker获得的图片自己手动保存在缓存中,这里简单做个文件存储

public let ZPHFile = ZPHFileManager.share

open class ZPHFileManager {

    let fileManager: FileManager = FileManager()

    static let share = ZPHFileManager()

    func write(_ filePath: String = "",_ name: String, _ data: Data) -> (Bool, String) {

        let DocumentsPath: String = "\(NSHomeDirectory())/Documents/"
        let path = "\(DocumentsPath)\(filePath)"
        let dataPath = "\(path)/\(name)"

        if !fileManager.fileExists(atPath: path) {
            do {
                try fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
            } catch {
                print("文件目录创建失败")
            }
        }

        return (fileManager.createFile(atPath: dataPath, contents: data, attributes: nil), dataPath)
    }
}

Flutter获取照片信息

flutter通过回调接收到图片后更新widget状态setState()

image: DecorationImage(
                image: _imageFile == null
                    ? AssetImage("asset/images/me_head_empty.png")
                    : FileImage(File(_imageFile)))


这样就可以展示原生的本地图片了,当然有很多优秀的第三方实现起来更方便简单,写的有问题欢迎指正。文章到这里就结束了,你也可以私信我及时获取最新资料。如果你有什么意见和建议欢迎给我留言。