Estou usando esta biblioteca de câmeras na qual o autor envolve um AVCaptureVideoPreviewLayer
dentro de um UIViewControllerRepresentable
( link ) para usá-lo como uma visualização da câmera. Dentro updateUIViewController
, o autor enfileira a frame
atualização com 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
}
}
Pode haver discrepâncias entre point A
e point B
, o que faz sentido, pois o uso DispatchQueue.main.async
não garante o pedido, mas não estou totalmente convencido de que essa abordagem esteja correta. Quero poder definir frame
essa visualização usando algo como Preview().frame(width: 350, height: 500)
. No entanto, a falta de ordem aqui significa que dependendo de outras partes do aplicativo/visualizações, a view.frame
atualização acontece em um cronograma desconhecido . Por exemplo, o seguinte:
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)
}
}
}
}
Impressões:
Point A: (0.0, 0.0, 393.0, 852.0)
Point B: (0.0, 0.0, 350.0, 500.0)
Mas se você alterar o código para outra coisa, talvez um plano de fundo diferente em .zIndex(0)
(não mostrarei o código exato aqui, pois meu aplicativo não é trivial), ele poderá imprimir:
Point A: (0.0, 0.0, 393.0, 852.0)
Point B: (0.0, 0.0, 393.0, 852.0)
Então minha pergunta é. Qual é a maneira correta de definir view.frame
? updateUIViewController
obviamente está sendo chamado em alguma ordem determinística, mas não antes de bound
"estabelecer". Não vejo um método mágico "updateViewOneLastTime"?
Parece que você está procurando
viewDidLayoutSubviews
, que é chamado sempre que o controlador de visualização éview.bounds
alterado. Crie umaUIViewController
subclasse e substitua-a.Em seguida, altere os métodos na
UIViewControllerRepresentable
implementação para usar esta subclasse. Passe a camada de visualização para a subclasse do controlador de visualização, quando apropriado.