swiftui - ZoomableScrollView 不再适用于 SwiftUI
问题描述
使用 Swift 5.5、Xcode 13.0、iOS 15.0.1、
由于 Apple 在 SwiftUI 的 ScrollViews 上做得不好(还没有?),我不得不实现自己的可缩放 ScrollView。请参阅下面的代码。
我让它在 iOS13 和 iOS14 上成功运行 - 但现在更新到iOS 15.0.1
我不得不意识到它不再有效!
错误信息如下:
objc[10882]: Cannot form weak reference to instance (0x1078d5540) of class _TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_5ImageVS_18_AspectRatioLayout__. It is possible that this object was over-released, or is in the process of deallocation.
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
(lldb)
我在SwiftUIPager中拥有所有内容,滑动时问题出现在最后一页。但是,我认为这不是寻呼机的错误,因为我可以用普通的 ImageView 替换 ZoomableScrollView 并且一切正常。因此,我认为 Apple 在他们的 UIViewRepresentable 中搞砸了一些东西。但也许你可以告诉我更多?
这是我的 ZoomableScrollView 的完整代码:
import SwiftUI
struct ZoomableScrollView<Content: View>: UIViewRepresentable {
@Binding var didZoom: Bool
private var content: Content
init(didZoom: Binding<Bool>, @ViewBuilder content: () -> Content) {
_didZoom = didZoom
self.content = content()
}
func makeUIView(context: Context) -> UIScrollView {
// set up the UIScrollView
let scrollView = UIScrollView()
scrollView.delegate = context.coordinator // for viewForZooming(in:)
scrollView.maximumZoomScale = 20
scrollView.minimumZoomScale = 1
scrollView.bouncesZoom = true
// create a UIHostingController to hold our SwiftUI content
let hostedView = context.coordinator.hostingController.view!
hostedView.translatesAutoresizingMaskIntoConstraints = true
hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
hostedView.frame = scrollView.bounds
hostedView.backgroundColor = .black
scrollView.addSubview(hostedView)
return scrollView
}
func makeCoordinator() -> Coordinator {
return Coordinator(hostingController: UIHostingController(rootView: self.content), didZoom: $didZoom)
}
func updateUIView(_ uiView: UIScrollView, context: Context) {
// update the hosting controller's SwiftUI content
context.coordinator.hostingController.rootView = self.content
assert(context.coordinator.hostingController.view.superview == uiView)
}
// MARK: - Coordinator
class Coordinator: NSObject, UIScrollViewDelegate {
var hostingController: UIHostingController<Content>
@Binding var didZoom: Bool
init(hostingController: UIHostingController<Content>, didZoom: Binding<Bool>) {
self.hostingController = hostingController
_didZoom = didZoom
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return hostingController.view
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
didZoom = !(scrollView.zoomScale == scrollView.minimumZoomScale)
}
}
}
解决方案
我终于找到了解决方法。
在类中添加以下代码ZoomableScrollView-UIViewRepresentable
:
static func dismantleUIView(_ uiView: UIScrollView, coordinator: Coordinator) {
uiView.delegate = nil
coordinator.hostingController.view = nil
}
推荐阅读
- python-3.x - 这个错误怎么可能发生,可以做些什么呢?“ValueError:int() 的无效文字,基数为 10:'1.0'”
- linux - 将名称中带有图案的文件移动到与其名称相同图案的文件夹中
- android - Activity getIntent 和 TaskStackBuilder getIntent() 有什么区别?
- kubernetes - 如何通过 cert-manager 使用 Let's Encrypt 的通配符证书
- javascript - 抓取的页面仅在 Microsoft Edge 中呈现
- java - 删除 Kafka StateStore 中的记录不起作用(在 .delete(key) 上抛出 NullPointerException)
- sql - 如何设置列以在选择语句中返回值
- php - 为什么 AJAX 在我的 PHP 应用程序中不起作用?
- c - C 程序输出复杂度
- javascript - Webpack / React:内联加载程序在不被调用的情况下执行(具有动态导入的内联加载程序的意外行为)