• SwiftUI调用相机拍照


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

    1. 创建一个 ImagePicker 组件

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

    import SwiftUI
    import UIKit
    
    struct 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 SwiftUI
    
    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()
        }
    }
    

    解释

    1. ImagePicker 组件

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

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

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

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

    添加 NSCameraUsageDescriptionInfo.plist

    1. 打开你的 Xcode 项目。

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

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

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

    示例:

    <key>NSCameraUsageDescriptionkey>
    <string>This app requires access to the camera to take photos.string>
    

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

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

    更新后的示例代码

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

    import SwiftUI
    import UIKit
    
    struct 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,应用在请求访问相机时会向用户显示一条提示,解释为什么需要访问相机,从而避免因未声明权限而导致的崩溃。

  • 相关阅读:
    springboot爱护大自然的设计与实现毕业设计源码231643
    java基于springboot教学评价管理系统附源码
    简单的前端语言
    【斗破年番】导演紧急删减第66集预告,陨落心炎事件要重演?
    3-2主机发现-三层发现
    提高编程效率专辑—数据导入工具①
    聊一聊HTTPS双向认证的简单应用
    3ds Max渲染太慢?创意云“一键云渲染”提升3ds Max渲染体验
    SQL模板-用户留存率计算
    unity解码4k图片过慢,使用turbojpeg加速,使用opencl加速,使用libjpeg,使用v4l2
  • 原文地址:https://blog.csdn.net/zhbzhb324/article/details/139329890