首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用UIViewControllerRepresentable更新值时弹出崩溃

使用UIViewControllerRepresentable更新值时弹出崩溃
EN

Stack Overflow用户
提问于 2021-10-10 13:46:11
回答 1查看 234关注 0票数 0

我想在iPhone上做弹出,我注意到当在iPhone中使用.popover时,它总是显示为工作表,而在iPad上,它将显示为popover。

所以我决定使用UIKit版本,一切正常,直到我点击按钮来更新视图

它将因此错误而崩溃。

代码语言:javascript
复制
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally a view controller <_TtGC7SwiftUI19UIHostingControllerGVS_6HStackGVS_9TupleViewTGVS_6ButtonVS_4Text_S4_GS3_S4______: 0x7fd47b424df0> that is already being presented by <UIViewController: 0x7fd47b426200>.

我的代码:

代码语言:javascript
复制
struct PopoverViewModifier<PopoverContent>: ViewModifier where PopoverContent: View {
    @Binding var isPresented: Bool
    let onDismiss: (() -> Void)?
    let content: () -> PopoverContent

    func body(content: Content) -> some View {
        content
            .background(
                Popover(
                    isPresented: self.$isPresented,
                    onDismiss: self.onDismiss,
                    content: self.content
                )
            )
    }
}

extension View {
    func popover<Content>(
        isPresented: Binding<Bool>,
        onDismiss: (() -> Void)? = nil,
        content: @escaping () -> Content
    ) -> some View where Content: View {
        ModifiedContent(
            content: self,
            modifier: PopoverViewModifier(
                isPresented: isPresented,
                onDismiss: onDismiss,
                content: content
            )
        )
    }
}

struct Popover<Content: View> : UIViewControllerRepresentable {
    @Binding var isPresented: Bool
    let onDismiss: (() -> Void)?
    @ViewBuilder let content: () -> Content

    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self, content: self.content())
    }

    func makeUIViewController(context: Context) -> UIViewController {
        return UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        let host = context.coordinator.host
        if self.isPresented {
            host.preferredContentSize = host.sizeThatFits(in: CGSize(width: Int.max , height: Int.max))
            host.modalPresentationStyle = UIModalPresentationStyle.popover
            host.popoverPresentationController?.delegate = context.coordinator
            host.popoverPresentationController?.sourceView = uiViewController.view
            host.popoverPresentationController?.sourceRect = uiViewController.view.bounds
            uiViewController.present(host, animated: true, completion: nil)
        }
        else {
            host.dismiss(animated: true, completion: nil)
        }
    }

    class Coordinator: NSObject, UIPopoverPresentationControllerDelegate {
        let host: UIHostingController<Content>
        private let parent: Popover

        init(parent: Popover, content: Content) {
            self.parent = parent
            self.host = UIHostingController(rootView: content)
        }

        func presentationControllerWillDismiss(_ presentationController: UIPresentationController) {
            self.parent.isPresented = false
            if let onDismiss = self.parent.onDismiss {
                onDismiss()
            }
        }

        func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
            return .none
        }
    }
}

我如何使用它:

代码语言:javascript
复制
struct ContentView: View {
@State var openChangeFont = false
@State var currentFontSize = 0

var body: some View {
    
    NavigationView {

        Text("Test")
          
  
        .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    Text("Popover")
                        .popover(isPresented: $openChangeFont, content: {
                            HStack {
                                
                                Button(action: {
                                    DispatchQueue.main.async {
                                        currentFontSize += 2
                                    }
                                }, label: {
                                    Text("Increase")
                                })
                                
                                Text("\(currentFontSize)")
                                
                                Button(action: {
                                    currentFontSize -= 2

                                }, label: {
                                    Text("Decrease")
                                })

                            }
                    })
                        .onTapGesture {
                            openChangeFont.toggle()
                    }
                }
}
}

}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-10 15:15:12

Popover.updateUIViewController中放置一个断点,我认为您会发现问题的。每次更新updateUIViewController视图时都会调用SwiftUI,这意味着当isPresented为true时可能会调用该视图,而您已经显示了弹出窗口。

如果这是问题所在,那么您需要跟踪您是否已经提交了该弹出。您已经在实现UIPopoverPresentationControllerDelegate,因此可以使用它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69515727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档