![](/img/trans.png)
[英]SwiftUI NavigationLink pops automatically which is unexpected
[英]SwiftUI Unexpectedly NavigationLink pops automatically
我有一个简单的用例,其中一个屏幕使用 NavigationLink 推送另一个屏幕。 iOS 14.5 有一个奇怪的行为,其中被推送的屏幕在被推送后立即弹出。
代码:
NavigationLink(destination: EmptyView()) { EmptyView()}
我设法创建了一个示例应用程序,并在其中复制它。 我相信原因是@Environment(\.presentationMode)
的存在似乎重新创建了视图,并导致推送的视图被弹出。
完全相同的代码在 Xcode 12 / iOS 14.4 中工作正常
从上周开始,我就陷入了困境。 为了解决这个问题,我只是将它添加到包含我现有NavigationLink
的视图中:
NavigationLink(destination: EmptyView()) {
EmptyView()
}
对于这个可怕的错误,我永远找不到可靠的解决方案。 所以我决定创建一个自定义 NavigationLink,使用Introspect ( https://github.com/siteline/SwiftUI-Introspect )。 这比预期的要好得多,因为所有 swiftui 相关功能继续照常工作。 似乎该错误专门针对 NavigationLink。
private struct NavigationLinkImpl<Destination: View, Label: View>: View {
let destination: () -> Destination?
@State var isActive = false
@ViewBuilder let label: () -> Label
var body: some View {
NavigationLinkImpl1(destination: destination, isActive: $isActive, label: label)
}
}
private struct NavigationLinkImpl1<Destination: View, Label: View>: View {
let destination: () -> Destination
@Binding var isActive: Bool
@ViewBuilder let label: () -> Label
@State var model = Model()
var body: some View {
Button(action: action, label: label)
.introspectNavigationController(customize: handle)
.id(isActive)
}
func handle(nav: UINavigationController) {
if isActive {
if model.destination == nil {
let dest = UIHostingController<Destination>(rootView: destination())
nav.pushViewController(dest, animated: true)
model.destination = dest
}
} else {
if let dest = model.destination {
if let i = nav.viewControllers.lastIndex(of: dest) {
nav.setViewControllers(.init(nav.viewControllers.prefix(i + 1)), animated: true)
}
model.destination = nil
}
}
if isActive != model.contains(nav: nav) { // detect pop
isActive = model.contains(nav: nav)
}
}
final class Model {
var destination: UIHostingController<Destination>?
func contains(nav: UINavigationController) -> Bool { destination.map { nav.viewControllers.contains($0) } ?? false }
}
func action() { isActive = true }
}
extension NavigationLink {
init<Destination: View, Label: View>(destination: @autoclosure @escaping () -> Destination, @ViewBuilder label: @escaping () -> Label) {
self.init(body: NavigationLinkImpl(destination: destination, label: label))
}
init<Destination: View, Label: View>(destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>, @ViewBuilder label: @escaping () -> Label) {
self.init(body: NavigationLinkImpl1(destination: destination, isActive: isActive, label: label))
}
init<Destination: View>(_ text: String, destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>) {
self.init(destination: destination(), isActive: isActive) { Text(text) }
}
init<Destination: View>(_ text: String, destination: @autoclosure @escaping () -> Destination) {
self.init(destination: destination()) { Text(text) }
}
}
把它放在一个文件中,你现有的 NavigationLinks 就可以正常工作了。 在 ios 14 和 15 中测试
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.