#swiftui #avfoundation #swift5 #ios-camera
#swiftui #avfoundation #swift5 #ios-камера
Вопрос:
Я пытаюсь реализовать предварительный просмотр камеры в SwiftUI, для чего у меня есть следующий код:
import SwiftUI
import AVFoundation
struct CameraPreview: UIViewRepresentable {
let session: AVCaptureSession
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = .gray
let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
videoPreviewLayer.frame = view.bounds
videoPreviewLayer.videoGravity = .resizeAspectFill
videoPreviewLayer.connection?.videoOrientation = .portrait
view.layer.addSublayer(videoPreviewLayer)
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
for layer in uiView.layer.sublayers ?? [] {
layer.frame = uiView.bounds
}
}
}
Однако я вижу вид серого фона, который я установил в представлении, но он никогда не начинает показывать выходные данные камеры. Я установил AVCaptureVideoDataOutputSampleBufferDelegate
класс, и я вижу, что кадры захватываются и обрабатываются, но по какой-то причине он не начинает визуализировать выходные данные.
У меня есть этот другой фрагмент, который отображает выходные данные, но он делает это, устанавливая слой предварительного просмотра в качестве корневого слоя, чего я хочу избежать, вот код, который работает:
struct CameraPreview: UIViewRepresentable {
let session: AVCaptureSession
func makeUIView(context: Context) -> UIView {
let view = VideoView()
view.backgroundColor = .gray
view.previewLayer.session = session
view.previewLayer.videoGravity = .resizeAspectFill
view.previewLayer.connection?.videoOrientation = .portrait
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
for layer in uiView.layer.sublayers ?? [] {
layer.frame = uiView.bounds
}
}
class VideoView: UIView {
override class var layerClass: AnyClass {
AVCaptureVideoPreviewLayer.self
}
var previewLayer: AVCaptureVideoPreviewLayer {
layer as! AVCaptureVideoPreviewLayer
}
}
}
Некоторые примеры, которые я нашел, показали, что я должен иметь возможность показывать предварительный просмотр, как в первом примере. Я пробовал инициализировать сеанс с помощью входных данных до и после создания предварительного просмотра, и я получил тот же результат. Я что-то пропустил? я не сохраняю слой или есть специальная конфигурация для сеанса, на которую нужно обратить внимание? чтобы заставить это работать, я просто меняю местами реализации, и та, у которой есть внутренний класс, выполняет рендеринг?
Любая помощь действительно ценится.
Некоторые ресурсы:
Комментарии:
1. Вы пробовали устанавливать
zPosition
для слоя значение > 0?2. Кроме того, мне на самом деле больше нравится второй подход (с
VideoView
), поскольку вам на самом деле не нужно обновлять фрейм слояupdateUIView
. Размер слоя всегда должен изменяться вместе с видом.3. @FrankSchlegel Я только что сделал, тот же результат. Я действительно могу удалить код внутри
updateUIView
, и это никак не влияет на оба фрагмента.