我正在使用这个相机库,作者将一个包装在(链接AVCaptureVideoPreviewLayer
)内,以将其用作相机预览。在里面,作者使用以下方式排队更新:UIViewControllerRepresentable
updateUIViewController
frame
DispatchQueue.main.async
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
previewLayer.videoGravity = gravity
if previewLayer.superlayer == nil {
uiViewController.view.layer.addSublayer(previewLayer)
}
// print(uiViewController.view.bounds) -- point A
DispatchQueue.main.async {
// print(uiViewController.view.bounds) -- point B
self.previewLayer.frame = uiViewController.view.bounds
}
}
point A
和之间可能存在差异point B
,这是有道理的,因为使用DispatchQueue.main.async
不能保证排序,但我并不完全相信这种方法是正确的。我希望能够frame
使用类似 来设置此视图的Preview().frame(width: 350, height: 500)
。但是,这里缺乏排序意味着根据应用程序/视图的其他部分,更新view.frame
会按照未知的时间表进行。例如,以下内容:
import SwiftUI
import Aespa
@Observable
class ViewModel {
@ObservationIgnored var aespaSession = Aespa.session(with: AespaOption(albumName: nil))
@ObservationIgnored var preview: InteractivePreview {
aespaSession.interactivePreview(
gravity: .resizeAspectFill,
option: InteractivePreviewOption()
)
}
var show = false
}
struct ContentView: View {
@State var viewModel = ViewModel()
var body: some View {
ZStack {
VStack {
Spacer()
Button("Show Camera Preview") {
viewModel.show.toggle()
}
}
.ignoresSafeArea()
.zIndex(0)
if viewModel.show {
VStack {
viewModel.preview
.frame(width: 350, height: 500)
Spacer()
}
.zIndex(1)
}
}
}
}
印刷:
Point A: (0.0, 0.0, 393.0, 852.0)
Point B: (0.0, 0.0, 350.0, 500.0)
但是如果你将代码更改为其他内容,也许是不同的背景.zIndex(0)
(由于我的应用程序并不简单,所以我不会在这里显示确切的代码),它可能会打印:
Point A: (0.0, 0.0, 393.0, 852.0)
Point B: (0.0, 0.0, 393.0, 852.0)
所以我的问题是。设置 的正确方法是什么view.frame
?updateUIViewController
显然是按照某种确定的顺序调用的,但不是在“稳定”之前调用bound
的。我没有看到神奇的“updateViewOneLastTime”方法?
听起来您正在寻找
viewDidLayoutSubviews
,每当视图控制器发生view.bounds
变化时都会调用它。创建一个UIViewController
子类并覆盖它。然后更改实现中的方法
UIViewControllerRepresentable
以使用此子类。在适当的情况下将预览层传递给视图控制器子类。