我原本以为前者只是后者的重新导出,但看起来并非如此。这两个pin!
宏有什么区别,如何决定使用哪一个?
bli00's questions
我正在使用这个相机库,作者将一个包装在(链接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”方法?
CLLocationManager
提供了一种通过委托locationManagerDidChangeAuthorization
方法对授权更改做出反应的方法,但我找不到其他权限类型的等效方法。也就是说,相机访问或照片库访问似乎没有提供任何方法来对用户设置和更改授权做出反应。
我想我可以深入研究我调用的每种方法并捕获与该功能的权限被拒绝相关的任何错误,但这确实是一种低劣的方法。有没有一种方法可以确定地对 iOS 开发的授权更改做出反应?
我有一个名为的方法render
,该方法在每一帧上都会被调用,以使用 Metal 在屏幕上绘制一些东西。它正在渲染存储在类中的一些点数组。但是,我偶尔需要更新这个点数组。我正在努力想出一个可以以并发安全的方式更新这些点的解决方案。
也就是说,当render
尝试访问此数组时,另一个线程可能正在更新它,从而导致崩溃。此外,render
是同步的,无法阻止或等待更新。这似乎是一个常见的并发问题,所以我在这里寻求帮助,看看有什么解决方案。
概括一下这个问题——有一些同步函数被非常频繁地调用,它需要访问可以由另一个线程更新的数据。我确实可以控制该render
方法和执行更新的“其他”线程。我怎样才能防止竞争条件导致应用程序崩溃?(它必须不崩溃,没有数据“正确性”的考虑)
我假设的一个可能的解决方案是使用原子,但我并不完全确定如何做到这一点,特别是在 Swift 中(不认为 Swift 有原子吗?)
编辑:
我将尝试在这里添加更多背景信息,但考虑到我正在实现的部分内容藏在我无法访问的私人存储库中,添加 MRE 可能会很困难。
简而言之,我正在尝试按照此示例实现 MapBox 自定义图层。示例中此特定函数的细节render
无关紧要,因为我的渲染方法需要执行完全不同的事情,但它在伪代码中看起来像这样:
class MyCustomLayer: NSObject, CustomLayerHost {
var locationData: [CLLocation] = []
func render(...) {
// calculate the viewport from the parameters
let viewport = ...
if viewport.fitSomeCondition {
// fetch new location data. This can't block and needs to happen async
fetchLocationDataFromServer(viewport: viewport)
// need to somehow update the locationData
}
// render locationData
}
}
这里locationData
是经度和纬度的数组,是MapBox iOS SDK协议的render
一部分。如何处理的源代码尚未公开,但这里是标题声明:CustomLayerHost
CustomLayerHost
/**
* Render the layer. This method is called once per frame.
*
* This method is called if underlying map rendering backend uses Metal graphic API.
*
* @param The `parameters` that define the current camera position.
* @param The MTLCommandBuffer used to render all map layers.
* Use to create new command encoders. Do not submit as there could be map
* layers following this custom layer in style's layer list and those won't get
* to be encoded.
* @param The MTLRenderPassDescriptor that defines rendering map to view drawable.
*
*/
- (void)render:(nonnull MBMCustomLayerRenderParameters *)parameters
mtlCommandBuffer:(nonnull id<MTLCommandBuffer>)mtlCommandBuffer
mtlRenderPassDescriptor:(nonnull MTLRenderPassDescriptor *)mtlRenderPassDescriptor;
我知道这不是 MRE,但我希望这有助于更清楚地解释这个问题。
我有一个视图,顶部是 a Map
,底部是 rounded View
,当前,当显示此屏幕时,视图Map
停止在两个视图相交处,有一个非常明显的间隙,是否有一种方法可以将两者无缝合并在一起,以便地图看起来好像在背景中?
VStack {
Map(position: $position) {
UserAnnotation()
}
.mapStyle(.standard(elevation: .realistic))
.ignoresSafeArea()
List {
ForEach(locationManager.debugMessages, id: \.self) { msg in
Text(msg)
}
}
.cornerRadius(30)
}