赞
踩
在 SwiftUI 中实现拍照功能,需要结合 UIViewControllerRepresentable
和 UIImagePickerController
来实现相机功能。下面是一个详细的示例,展示如何使用 SwiftUI 来实现拍照功能:
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) {} }
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() } }
ImagePicker
组件:
UIViewControllerRepresentable
协议用来将 UIImagePickerController
引入 SwiftUI。makeUIViewController
和 updateUIViewController
方法创建和更新 UIImagePickerController
。Coordinator
类作为 UIImagePickerController
的代理,处理图片选择和取消操作。ContentView
:
@State
属性包装变量 isImagePickerPresented
来控制 ImagePicker
的显示。@State
属性包装变量 selectedImage
来存储选取的图片。ImagePicker
。sheet
修饰符用于在 isImagePickerPresented
为 true
时呈现 ImagePicker
。通过这种方式,你可以在 SwiftUI 应用中实现拍照功能。请注意,拍照功能只能在真实设备上使用,因为模拟器不支持摄像头。
在 iOS 应用中访问相机需要在 Info.plist
文件中添加 NSCameraUsageDescription
键,以告知用户为什么需要访问相机。否则,应用在尝试访问相机时会崩溃。
NSCameraUsageDescription
到 Info.plist
打开你的 Xcode 项目。
在项目导航中,找到并点击你的 Info.plist
文件。
在 Info.plist
中,添加一个新的键值对:
NSCameraUsageDescription
<key>NSCameraUsageDescription</key>
<string>This app requires access to the camera to take photos.</string>
如果你使用 Xcode 的图形化界面,可以按以下步骤操作:
Info.plist
文件。NSCameraUsageDescription
。完成上述步骤后,你可以重新运行之前的代码:
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
,应用在请求访问相机时会向用户显示一条提示,解释为什么需要访问相机,从而避免因未声明权限而导致的崩溃。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。