将 UIViewRepresentable 连接到 SwiftUI
Connect UIViewRepresentable to SwiftUI
我有一个基于 SwiftUI 的应用程序,它有一个简单的按钮,当按下该按钮时应该会打开来自 AVFoundation 的相机 Class,它也使用 UIKit。在 sheet 下,我不确定该放什么。我尝试了 CameraSession() 和其他一些想法,但我有点迷失了桥接此 SwiftUI 按钮以打开相机应用程序。谢谢!
//内容视图
import SwiftUI
struct ContentView: View {
//@State private var image: Image?
@State private var showingCameraSession = false
//@Binding var isShown: Bool
var body: some View {
VStack{
ControlButton(systemIconName: "slider.horizontal.3"){
//Button("Seelect Image") {
showingCameraSession = true
} .sheet(isPresented: $showingCameraSession){
//What to place here?
}
}
}
}
//相机会话
import AVFoundation
//import RealityKit
import UIKit
import SwiftUI
struct CameraSession : UIViewControllerRepresentable {
//@Binding var isShown: Bool
typealias UIViewControllerType = CaptureSession
func makeUIViewController(context: Context) -> CaptureSession{
return CaptureSession()
}
func updateUIViewController(_ uiViewController: CaptureSession, context: Context) {
// if(self.isShown){
//CameraSession.didTapTakePhoto()
// shutterButton.addTarget(self, action: #selector(didTapTakePhoto), for: .touchUpInside) //tie button to actual function
}
}
class CaptureSession: UIViewController {
//@Binding var isShown: Bool
//Reference: https://www.youtube.com/watch?v=ZYPNXLABf3c
//CaptureSession
var session: AVCaptureSession?
//PhotoOutput --> to the Cloud
let output = AVCapturePhotoOutput()
// Video Preview
let previewLayer = AVCaptureVideoPreviewLayer()
//Shutter Button
private let shutterButton: UIButton = {
let button = UIButton(frame: CGRect(x:0, y:0, width: 100, height: 100))
button.layer.cornerRadius = 50
button.layer.borderWidth = 10
button.layer.borderColor = UIColor.white.cgColor
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
//previewLayer.backgroundColor = UIColor.systemRed.cgColor
view.layer.addSublayer(previewLayer)
view.addSubview(shutterButton)
checkCameraPermissions()
shutterButton.addTarget(self, action: #selector(didTapTakePhoto), for: .touchUpInside) //tie button to actual function
}
override func viewDidLayoutSubviews(){
super.viewDidLayoutSubviews()
previewLayer.frame = view.bounds
shutterButton.center = CGPoint(x: view.frame.size.width/2, y: view.frame.size.height - 100)
}
private func checkCameraPermissions() {
switch AVCaptureDevice.authorizationStatus(for: .video){
case .notDetermined:
//Request Permission
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
guard granted else {
return
}
DispatchQueue.main.async{
self?.setUpCamera()
}
}
case .restricted:
break
case .denied:
break
case .authorized:
setUpCamera()
@unknown default:
break
}
}
//with Photogrammetry, you also have to create a session similar https://developer.apple.com/documentation/realitykit/creating_3d_objects_from_photographs/
// example app: https://developer.apple.com/documentation/realitykit/taking_pictures_for_3d_object_capture
private func setUpCamera(){
let session = AVCaptureSession()
if let device = AVCaptureDevice.default(for: .video){
do{
let input = try AVCaptureDeviceInput(device: device)
if session.canAddInput(input){
session.addInput(input) //some Devices contract each other.
}
if session.canAddOutput(output) {
session.addOutput(output)
}
previewLayer.videoGravity = .resizeAspectFill //content does not get distored or filled
previewLayer.session = session
session.startRunning()
self.session = session
}
catch{
print(error)
}
}
}
//originally private
@objc private func didTapTakePhoto() {
output.capturePhoto(with: AVCapturePhotoSettings(),
delegate: self)
// let vc = UIHostingController(rootView: ContentView())
// present(vc, animated: true)
}
}
//AVCaptureOutput is AVFoundations version of photo output
extension CaptureSession: AVCapturePhotoCaptureDelegate {
func photoOutput( output: AVCaptureOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error:
Error?){
guard let data = photo.fileDataRepresentation() else { //where to store file information
return
}
let image = UIImage(data: data)
session?.stopRunning()
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = view.bounds
view.addSubview(imageView)
}
}
因此,为了解决这个问题,首先让您的应用有权访问用户相机(转到 Info.plist 或顶部构建设置旁边的信息选项卡,添加隐私相机使用并添加“我们需要您的相机执行此操作")
之后,在 sheet 的修饰符中进行简单调用即可解决问题
struct ContentView: View {
//@State private var image: Image?
@State private var showingCameraSession = false
//@Binding var isShown: Bool
var body: some View {
VStack{
// ControlButton(systemIconName: "slider.horizontal.3"){
Button("Seelect Image") {
showingCameraSession = true
} .sheet(isPresented: $showingCameraSession){
//What to place here?
CameraSession()
}
}
}
}
我有一个基于 SwiftUI 的应用程序,它有一个简单的按钮,当按下该按钮时应该会打开来自 AVFoundation 的相机 Class,它也使用 UIKit。在 sheet 下,我不确定该放什么。我尝试了 CameraSession() 和其他一些想法,但我有点迷失了桥接此 SwiftUI 按钮以打开相机应用程序。谢谢!
//内容视图
import SwiftUI
struct ContentView: View {
//@State private var image: Image?
@State private var showingCameraSession = false
//@Binding var isShown: Bool
var body: some View {
VStack{
ControlButton(systemIconName: "slider.horizontal.3"){
//Button("Seelect Image") {
showingCameraSession = true
} .sheet(isPresented: $showingCameraSession){
//What to place here?
}
}
}
}
//相机会话
import AVFoundation
//import RealityKit
import UIKit
import SwiftUI
struct CameraSession : UIViewControllerRepresentable {
//@Binding var isShown: Bool
typealias UIViewControllerType = CaptureSession
func makeUIViewController(context: Context) -> CaptureSession{
return CaptureSession()
}
func updateUIViewController(_ uiViewController: CaptureSession, context: Context) {
// if(self.isShown){
//CameraSession.didTapTakePhoto()
// shutterButton.addTarget(self, action: #selector(didTapTakePhoto), for: .touchUpInside) //tie button to actual function
}
}
class CaptureSession: UIViewController {
//@Binding var isShown: Bool
//Reference: https://www.youtube.com/watch?v=ZYPNXLABf3c
//CaptureSession
var session: AVCaptureSession?
//PhotoOutput --> to the Cloud
let output = AVCapturePhotoOutput()
// Video Preview
let previewLayer = AVCaptureVideoPreviewLayer()
//Shutter Button
private let shutterButton: UIButton = {
let button = UIButton(frame: CGRect(x:0, y:0, width: 100, height: 100))
button.layer.cornerRadius = 50
button.layer.borderWidth = 10
button.layer.borderColor = UIColor.white.cgColor
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
//previewLayer.backgroundColor = UIColor.systemRed.cgColor
view.layer.addSublayer(previewLayer)
view.addSubview(shutterButton)
checkCameraPermissions()
shutterButton.addTarget(self, action: #selector(didTapTakePhoto), for: .touchUpInside) //tie button to actual function
}
override func viewDidLayoutSubviews(){
super.viewDidLayoutSubviews()
previewLayer.frame = view.bounds
shutterButton.center = CGPoint(x: view.frame.size.width/2, y: view.frame.size.height - 100)
}
private func checkCameraPermissions() {
switch AVCaptureDevice.authorizationStatus(for: .video){
case .notDetermined:
//Request Permission
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
guard granted else {
return
}
DispatchQueue.main.async{
self?.setUpCamera()
}
}
case .restricted:
break
case .denied:
break
case .authorized:
setUpCamera()
@unknown default:
break
}
}
//with Photogrammetry, you also have to create a session similar https://developer.apple.com/documentation/realitykit/creating_3d_objects_from_photographs/
// example app: https://developer.apple.com/documentation/realitykit/taking_pictures_for_3d_object_capture
private func setUpCamera(){
let session = AVCaptureSession()
if let device = AVCaptureDevice.default(for: .video){
do{
let input = try AVCaptureDeviceInput(device: device)
if session.canAddInput(input){
session.addInput(input) //some Devices contract each other.
}
if session.canAddOutput(output) {
session.addOutput(output)
}
previewLayer.videoGravity = .resizeAspectFill //content does not get distored or filled
previewLayer.session = session
session.startRunning()
self.session = session
}
catch{
print(error)
}
}
}
//originally private
@objc private func didTapTakePhoto() {
output.capturePhoto(with: AVCapturePhotoSettings(),
delegate: self)
// let vc = UIHostingController(rootView: ContentView())
// present(vc, animated: true)
}
}
//AVCaptureOutput is AVFoundations version of photo output
extension CaptureSession: AVCapturePhotoCaptureDelegate {
func photoOutput( output: AVCaptureOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error:
Error?){
guard let data = photo.fileDataRepresentation() else { //where to store file information
return
}
let image = UIImage(data: data)
session?.stopRunning()
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = view.bounds
view.addSubview(imageView)
}
}
因此,为了解决这个问题,首先让您的应用有权访问用户相机(转到 Info.plist 或顶部构建设置旁边的信息选项卡,添加隐私相机使用并添加“我们需要您的相机执行此操作")
之后,在 sheet 的修饰符中进行简单调用即可解决问题
struct ContentView: View {
//@State private var image: Image?
@State private var showingCameraSession = false
//@Binding var isShown: Bool
var body: some View {
VStack{
// ControlButton(systemIconName: "slider.horizontal.3"){
Button("Seelect Image") {
showingCameraSession = true
} .sheet(isPresented: $showingCameraSession){
//What to place here?
CameraSession()
}
}
}
}