所以下面是一个简单的图片拍摄我有 ViewController
final class TakePhotoViewController : UIViewController, AVCapturePhotoCaptureDelegate {
var captureSession : AVCaptureSession!
var cameraOutput : AVCapturePhotoOutput!
var previewLayer : AVCaptureVideoPreviewLayer!
let device = AVCaptureDevice.default(for: .video)!
override func viewDidLoad(){
print("viewDidLoad")
setupCameraLayouts()
}
private func setupCameraLayouts(){
print("setupCameraLayouts")
captureSession = AVCaptureSession()
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
captureSession.sessionPreset = AVCaptureSession.Preset.hd1920x1080
cameraOutput = AVCapturePhotoOutput()
previewLayer.frame = CGRect(x: view.frame.origin.x, y: view.frame.origin.y+view.frame.height/13, width: view.frame.width, height: view.frame.height/1.2475)
do {
try device.lockForConfiguration()
} catch {
return
}
device.focusMode = .continuousAutoFocus
device.unlockForConfiguration()
}
private func startCamera(){
print("startCamera")
if let input = try? AVCaptureDeviceInput(device: device) {
if captureSession.canAddInput(input) {
captureSession.addInput(input)
if captureSession.canAddOutput(cameraOutput){
captureSession.addOutput(cameraOutput)
view.layer.addSublayer(previewLayer)
captureSession.startRunning()
} else {
print("else in : captureSession.canAddOutput(cameraOutput)")
}
} else {
print("else in : captureSession.canAddInput(input)")
}
} else {
print("else in : input = try? AVCaptureDeviceInput(device: device)")
}
}
func cameraPressed(){
print("cameraPressed")
let settings = AVCapturePhotoSettings()
let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
let previewFormat = [
kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
kCVPixelBufferWidthKey as String: 160,
kCVPixelBufferHeightKey as String: 160
]
settings.previewPhotoFormat = previewFormat
cameraOutput.capturePhoto(with: settings, delegate: self)
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?){
print("photoOutput")
captureSession.stopRunning()
print("Got something")
}
}
extension TakePhotoViewController : UIViewControllerRepresentable {
public typealias UIViewControllerType = TakePhotoViewController
func makeUIViewController(context: UIViewControllerRepresentableContext<TakePhotoViewController>) -> TakePhotoViewController {
print("makeUIViewController")
return TakePhotoViewController()
}
func updateUIViewController(_ uiViewController: TakePhotoViewController, context: UIViewControllerRepresentableContext<TakePhotoViewController>) {
print("updateUIViewController")
}
}
如您所见,我使用 UIViewControllerRepresentable 对其进行了“包装”,因此我可以在 SwiftUI View 中使用它。除非有更好的方法,否则我发现这是唯一的方法。
下面是我调用它的 SwiftUI 类。
struct ContentView: View {
let TPVC = TakePhotoViewController()
var body: some View {
VStack {
TPVC.startCamera()
Button(action: {
self.TPVC.cameraPressed()
}) {
Text("Hello World")
.fontWeight(.bold)
.font(.title)
.padding()
.background(Color.purple)
.cornerRadius(40)
.foregroundColor(.white)
.padding(10)
.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.purple, lineWidth: 5)
)
}
}
}
}
所以我知道(从打印语句)正在调用 TakePhotoVC 并且 nil 错误变量(实际上,所有变量)不是 nil。 也就是说,当错误发生时(当我单击按钮时),各种变量(captureSession、CaptureOutput)为 nil,这会导致明显的错误。在 ContentView 中,我为类实例创建了一个变量,因此我可以随时引用它,但似乎如果您再次调用它,它会创建一个全新的类引用/实例
最佳答案
您的 ContentView 是一个结构,即。值,它会在每次 UI 刷新时重新创建,因此您的 TPVC 也会重新创建。
而且 UIViewControllerRepresentable 应该是一些在 ViewBuilder 中使用的 View 。所以这是你代码中的错误概念。
教程Interfacing with UIKit应该对你有帮助。
关于swift - 在 SwiftUI 类中调用包装的 UIViewController 函数时获取 nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58844520/