SwiftUI控件之 PhotosPicker

在 SwiftUI 中,有一个特殊的Picker(选择器),叫做PhotosPicker(相册选择器),使用它可以帮助快速获取手机相册中的照片。

创建一个 PhotosPicker

PhotosPicker本身并不属于 SwiftUI这个模块中,它属于PhotosUI模块,所以我们首先需要在头部导入这个模块:

1
import PhotosUI

使用 @State 定义一个变量用来和PhotosPicker进行绑定:

1
@State var selectedImages: PhotosPickerItem?

创建PhotoPicker

1
PhotosPicker("选择喜欢的照片", selection: $selectedImages)

此时的效果如下:

注意上图的效果为 iOS 17 以后的效果。

因为相册里面的照片属于用户的敏感隐私数据,所以访问的时候会有隐私数据的提示。一般情况下,Apple 希望我们在隐私设置中添加访问敏感隐私数据的使用说明。

点击我们都项目根目录,在TARGETS中找到Info选项,在Custom iOS Target Properties中添加一个访问手机相册说明。

添加的记录如下,它是以Key-Value的形式存在的:

使用选中后的照片

使用PhotosPicker选中后的照片为 PhotosPickerItem类型,我们要想让选中的照片使用Image进行显示需要使用 loadTransferable(type:completionHandler:) 方法,具体使用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
struct ContentView: View {
@State var selectedImages: PhotosPickerItem?
@State var avatarImage: Image?
var body: some View {
VStack {
PhotosPicker("选择喜欢的照片", selection: $selectedImages)
// 非空时显示
if let avatarImage {
avatarImage
.resizable()
.frame(width: 200, height: 200)
}
}
// 当前 selectedImages的值发生变化时调用
.onChange(of: selectedImages) { _ in
// 创建一个异步任务
Task {
// 将选中的 PhotosPickerItem 类型转换为要显示的 Image
if let image = try? await selectedImages?.loadTransferable(type: Image.self) {
avatarImage = image
return
}
}
}
}
}

在上面的代码中,实现的步骤如下:

  1. 使用@State 定义一个 Image类型的变量用来接收转换后的照片;
  2. 使用onChange修饰器监听selectedImages变量值的的变化,当发生变化时将新的值转换为Image进行显示;
  3. 转换的过程中使用了Task创建了异步任务配合loadTransferable方法使用;
  4. avataImage的值不为nil时显示照片。

配置 PhotosPicker 可选择的范围

在 iOS ,我们平时拍的照片、截图、录的视频或者下载保存的视频都是存储在相册中的,PhotosPicker提供了一个matching参数用来设置应用可以选择的相册范围。

例如,如果想要应用只能选择视频,可以像下面这样设置:

1
PhotosPicker("选择喜欢的照片", selection: $selectedImages, matching: .videos)

它来提供了很多的范围可选,例如:

  • panoramas:全景照片;

  • images: 所有照片;

  • videos: 所有视频;

  • screenshots: 截图

    ……