我在从链接深度链接到某个 SwiftUI 视图时遇到问题。
openTakeVC
就是所谓的深度链接。目前它要嵌入到 UINavigationController 中才能工作,如果我尝试仅呈现 UIHostingController 我会因以下错误而崩溃:
Thread 1: "Application tried to present modally a view controller <_TtGC7SwiftUI19UIHostingControllerV8uSTADIUM8TakeView_: 0x14680a000> that has a parent view controller <UINavigationController: 0x1461af000>."
如果未嵌入 UINavigationController 中,则关闭功能可以正常工作,但我只能使用 UINavigationController 深层链接该视图。
是否有解决此错误的方法或消除嵌入 UINavigationController 中的 UIHostingController 的方法?
func openTakeVC(take: TakeOBJ) {
DispatchQueue.main.async {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
if let _ = appDelegate.window?.rootViewController as? BannedViewController { return }
//let vc = TakeSingleViewController(nibName: "TakeSingleView", bundle: nil, take: take)
let vc = UIHostingController(rootView: TakeView(take: take))
let nav = UINavigationController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen
nav.setNavigationBarHidden(true, animated: false)
appDelegate.window?.rootViewController?.present(vc, animated: true, completion: nil)
UserDefaults.removeURLToContinue()
}
}
在
TakeView
@Environment(\.presentationMode) var presentationMode
Button {
UIImpactFeedbackGenerator(style: .light).impactOccurred()
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "xmark")
}
}
将托管控制器创建为单独的 vc 并从那里将其关闭怎么样?
采取单VC:
final class TakeSingleVC: UIViewController {
var viewModel: TakeViewModel
var subscriptions = Set<AnyCancellable>()
init(viewModel: TakeViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
let childView = UIHostingController(rootView: TakeView(viewModel: viewModel))
addChild(childView)
childView.view.frame = view.bounds
view.addSubview(childView.view)
childView.didMove(toParent: self)
viewModel.dismissSheet
.sink { isDismissed in
if isDismissed {
childView.dismiss(animated: true)
}
}.store(in: &subscriptions)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
在 TakeView 中关闭
viewModel.dismissSheet.send(true)
获取ViewModel:
final class TakeViewModel: ObservableObject {
// UIKit
var dismissSheet = CurrentValueSubject<Bool, Never>(false)
}
然后将您的演示文稿更改为
let vc = TakeSingleVC(viewModel: viewModel)
let nav = UINavigationController(rootViewController: vc)
如果未嵌入 UINavigationController 中,则关闭功能可以正常工作,但我只能使用 UINavigationController 深层链接该视图。
是否有解决此错误的方法或消除错误的方法 UIHostingController 嵌入到 UINavigationController 中?
如果 UIHostingController 是 UINavigationController 堆栈的一部分,则通过 @Environment(.dismiss) 提供的 SwiftUI DismissAction 将无法与 UIHostingController 一起使用,即使 SwiftUI 按钮在导航栏中可用。
这是因为 DismissAction 根据上下文工作
您可以使用此操作来: 关闭模式演示,例如工作表或弹出框。 从 NavigationStack 中弹出当前视图。 关闭使用 WindowGroup 或 Window 创建的窗口。 该操作的具体行为取决于您从何处调用它。
https://developer.apple.com/documentation/SwiftUI/DismissAction
当 UIHostingController 位于 UINavigationController 内时,关闭操作(如果 UIHostingController 是导航堆栈中唯一的项目)将尝试从导航堆栈中弹出而不是关闭。
您可以通过为 UIHostingController 创建自己的自定义子类来绕过它,但我不推荐该路径。然而,这种方法有其局限性,因此不会将其发布在此处的答案中。
更安全的方法是通过闭包传递到 SwiftUI 视图,您自己的关闭操作。