小工具知识网

当前位置: 首页 > 行业知识 > SwiftUI调用相机拍照

行业知识

SwiftUI调用相机拍照

2026-11-11 06:28:52 来源:互联网转载

在 SwiftUI 中实现拍照功能,需要结合 UIViewControllerRepresentable 和 UIImagePickerController 来实现相机功能。下面是一个详细的示例,展示如何使用 SwiftUI 来实现拍照功能:

1. 创建一个 ImagePicker 组件

首先,创建一个 UIViewControllerRepresentable 结构,用于包装 UIImagePickerController。

import SwiftUIimport UIKitstruct ImagePicker: UIViewControllerRepresentable {    @Binding var selectedImage: UIImage?    @Environment(\.presentationMode) var presentationMode    var sourceType: UIImagePickerController.SourceType = .camera    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {        let parent: ImagePicker        init(parent: ImagePicker) {            self.parent = parent        }        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {            if let image = info[.originalImage] as? UIImage {                parent.selectedImage = image            }            parent.presentationMode.wrappedValue.dismiss()        }        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {            parent.presentationMode.wrappedValue.dismiss()        }    }    func makeCoordinator() -> Coordinator {        Coordinator(parent: self)    }    func makeUIViewController(context: Context) -> UIImagePickerController {        let picker = UIImagePickerController()        picker.delegate = context.coordinator        picker.sourceType = sourceType        return picker    }    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}}

2. 使用 ImagePicker 组件

接下来,在你的主视图中使用 ImagePicker 组件来实现拍照功能。

import SwiftUIstruct ContentView: View {    @State private var isImagePickerPresented = false    @State private var selectedImage: UIImage?    var body: some View {        VStack {            if let selectedImage = selectedImage {                Image(uiImage: selectedImage)                    .resizable()                    .scaledToFit()                    .frame(width: 300, height: 300)            } else {                Text("No Image Selected")                    .frame(width: 300, height: 300)                    .background(Color.gray)            }                        Button(action: {                isImagePickerPresented = true            }) {                Text("Take Photo")                    .padding()                    .background(Color.blue)                    .foregroundColor(.white)                    .cornerRadius(10)            }            .padding()        }        .sheet(isPresented: $isImagePickerPresented) {            ImagePicker(selectedImage: $selectedImage)        }    }}struct ContentView_Previews: PreviewProvider {    static var previews: some View {        ContentView()    }}

解释

  1. ImagePicker 组件:

    • UIViewControllerRepresentable 协议用来将 UIImagePickerController 引入 SwiftUI。
    • makeUIViewController 和 updateUIViewController 方法创建和更新 UIImagePickerController。
    • Coordinator 类作为 UIImagePickerController 的代理,处理图片选择和取消操作。
    • ContentView:

      • 使用 @State 属性包装变量 isImagePickerPresented 来控制 ImagePicker 的显示。
      • 使用 @State 属性包装变量 selectedImage 来存储选取的图片。
      • 当点击 “Take Photo” 按钮时,显示 ImagePicker。
      • sheet 修饰符用于在 isImagePickerPresented 为 true 时呈现 ImagePicker。

通过这种方式,你可以在 SwiftUI 应用中实现拍照功能。请注意,拍照功能只能在真实设备上使用,因为模拟器不支持摄像头。

在 iOS 应用中访问相机需要在 Info.plist 文件中添加 NSCameraUsageDescription 键,以告知用户为什么需要访问相机。否则,应用在尝试访问相机时会崩溃。

添加 NSCameraUsageDescription 到 Info.plist

  1. 打开你的 Xcode 项目。

  2. 在项目导航中,找到并点击你的 Info.plist 文件。

  3. 在 Info.plist 中,添加一个新的键值对:

    • 键:NSCameraUsageDescription
    • 值:解释你的应用需要使用相机的原因,比如 “This app requires access to the camera to take photos.”

示例:

NSCameraUsageDescriptionThis app requires access to the camera to take photos.

如果你使用 Xcode 的图形化界面,可以按以下步骤操作:

  1. 打开 Info.plist 文件。
  2. 点击右键选择 “Add Row”。
  3. 在新行的键列中输入 NSCameraUsageDescription。
  4. 在值列中输入对用户的说明,比如 “This app requires access to the camera to take photos.”

更新后的示例代码

完成上述步骤后,你可以重新运行之前的代码:

import SwiftUIimport UIKitstruct ImagePicker: UIViewControllerRepresentable {    @Binding var selectedImage: UIImage?    @Environment(\.presentationMode) var presentationMode    var sourceType: UIImagePickerController.SourceType = .camera    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {        let parent: ImagePicker        init(parent: ImagePicker) {            self.parent = parent        }        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {            if let image = info[.originalImage] as? UIImage {                parent.selectedImage = image            }            parent.presentationMode.wrappedValue.dismiss()        }        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {            parent.presentationMode.wrappedValue.dismiss()        }    }    func makeCoordinator() -> Coordinator {        Coordinator(parent: self)    }    func makeUIViewController(context: Context) -> UIImagePickerController {        let picker = UIImagePickerController()        picker.delegate = context.coordinator        picker.sourceType = sourceType        return picker    }    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}}struct ContentView: View {    @State private var isImagePickerPresented = false    @State private var selectedImage: UIImage?    var body: some View {        VStack {            if let selectedImage = selectedImage {                Image(uiImage: selectedImage)                    .resizable()                    .scaledToFit()                    .frame(width: 300, height: 300)            } else {                Text("No Image Selected")                    .frame(width: 300, height: 300)                    .background(Color.gray)            }                        Button(action: {                isImagePickerPresented = true            }) {                Text("Take Photo")                    .padding()                    .background(Color.blue)                    .foregroundColor(.white)                    .cornerRadius(10)            }            .padding()        }        .sheet(isPresented: $isImagePickerPresented) {            ImagePicker(selectedImage: $selectedImage)        }    }}struct ContentView_Previews: PreviewProvider {    static var previews: some View {        ContentView()    }}

通过添加 NSCameraUsageDescription,应用在请求访问相机时会向用户显示一条提示,解释为什么需要访问相机,从而避免因未声明权限而导致的崩溃。

上一篇:git之系列

下一篇:链接服务器怎么删除用户?