设置UIScrollView.appearance().delegate后重复进入页面报错的修复咨询
问题修复方案
核心问题根源
你遇到的错误是因为**全局修改UIScrollView.appearance()**导致的:
- 全局设置
UIScrollView.appearance().delegate会影响App内所有UIScrollView子类(包括ContentView中List的底层UICollectionView)。 - 当DetailView销毁后,其viewModel被释放,全局delegate指向无效内存,再次进入DetailView时触发野指针错误,抛出
unrecognized selector异常。 @State didLoad的逻辑无法解决全局配置的生命周期问题,因为全局appearance设置不会随View销毁而重置。
具体修复步骤
1. 移除全局UIScrollView.appearance()设置
彻底放弃全局修改,改为仅针对当前DetailView的ScrollView做配置,避免干扰其他视图。
2. 用自定义UIViewRepresentable封装ScrollView
创建一个仅作用于当前视图的自定义ScrollView,将delegate和bounces的配置限制在内部:
struct CustomScrollView<Content: View>: UIViewRepresentable { let content: Content let viewModel: YourViewModelType // 替换成你的ViewModel实际类型 @Binding var didLoad: Bool init(viewModel: YourViewModelType, didLoad: Binding<Bool>, @ViewBuilder content: () -> Content) { self.viewModel = viewModel self._didLoad = didLoad self.content = content() } func makeUIView(context: Context) -> UIScrollView { let scrollView = UIScrollView() scrollView.showsVerticalScrollIndicator = false // 初始化时设置bounces scrollView.bounces = viewModel.isOnTop // 仅首次加载时绑定delegate if didLoad { scrollView.delegate = context.coordinator didLoad = false } // 嵌入SwiftUI内容 let hostingVC = UIHostingController(rootView: content) hostingVC.view.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(hostingVC.view) NSLayoutConstraint.activate([ hostingVC.view.topAnchor.constraint(equalTo: scrollView.topAnchor), hostingVC.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), hostingVC.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), hostingVC.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), hostingVC.view.widthAnchor.constraint(equalTo: scrollView.widthAnchor) ]) return scrollView } func updateUIView(_ uiView: UIScrollView, context: Context) { // 实时响应viewModel中isOnTop的变化 uiView.bounces = viewModel.isOnTop } func makeCoordinator() -> Coordinator { Coordinator(viewModel: viewModel) } // 用Coordinator持有ViewModel,避免野指针 class Coordinator: NSObject, UIScrollViewDelegate { let viewModel: YourViewModelType init(viewModel: YourViewModelType) { self.viewModel = viewModel super.init() } // 在这里实现你需要的UIScrollViewDelegate方法 func scrollViewDidScroll(_ scrollView: UIScrollView) { viewModel.handleScrollOffset(scrollView.contentOffset.y) } } }
3. 修改DetailView使用自定义ScrollView
struct DetailView: View { @State private var didLoad = true let viewModel: YourViewModelType // 传入你的ViewModel实例 var body: some View { CustomScrollView(viewModel: viewModel, didLoad: $didLoad) { // 这里放原来ScrollView中的内容 } } }
4. 修复ContentView中的NavigationLink错误
你代码中写的Detail()是错误的,要对应你的View名称DetailView:
struct ContentView: View { var body: some View { NavigationView { List { ForEach(0..<5, id: \.self) { _ in NavigationLink( destination: { DetailView(viewModel: YourViewModel()) }, label: { Text("title") } ) } } } } }
内容的提问来源于stack exchange,提问作者Kirill Mirtyrosov
相关产品推荐
相关产品推荐

