I have an issue with Xcode 12 / iOS 14. Using multiple NavigationLinks in a sheet with NavigationView leads to NavigationLink entries staying highlighted after going back a page. This is not only a problem with the simulator. See the attached GIF:
Does anybody know how to fix this?
Similar question: SwiftUI - NavigationLink cell in a Form stays highlighted after detail pop (but that's not the problem here).
struct ContentView: View {
var body: some View {
Text("")
.sheet(isPresented: .constant(true), content: {
NavigationView {
Form {
Section {
NavigationLink("Link to ViewB", destination: ViewB())
}
}
.navigationBarTitle("ViewA")
}
})
}
}
struct ViewB: View {
@State var selection = 0
let screenOptions = ["a", "b", "c"]
var body: some View{
Form {
Section {
NavigationLink("Link to ViewC", destination: ViewC())
}
}
.navigationBarTitle("ViewB")
}
}
struct ViewC: View {
var body: some View{
Form {
Section {
Text("Test")
}
}
.navigationBarTitle("ViewC")
}
}
I've also run into this problem when using a NavigationLink
inside a sheet. My solution on iOS 14 has been too Swizzle didSelectRowAt:
of UITableView
. When the row is selected, I deselect it. There is more code for detecting if its in a sheet, etc, but this is the basic, get it working code:
extension UITableView {
@objc static func swizzleTableView() {
guard self == UITableView.self else {
return
}
let originalTableViewDelegateSelector = #selector(setter: self.delegate)
let swizzledTableViewDelegateSelector = #selector(self.nsh_set(delegate:))
let originalTableViewMethod = class_getInstanceMethod(self, originalTableViewDelegateSelector)
let swizzledTableViewMethod = class_getInstanceMethod(self, swizzledTableViewDelegateSelector)
method_exchangeImplementations(originalTableViewMethod!,
swizzledTableViewMethod!)
}
@objc open func nsh_set(delegate: UITableViewDelegate?) {
nsh_set(delegate: delegate)
guard let delegate = delegate else { return }
let originalDidSelectSelector = #selector(delegate.tableView(_:didSelectRowAt:))
let swizzleDidSelectSelector = #selector(self.tableView(_:didSelectRowAt:))
let swizzleMethod = class_getInstanceMethod(UITableView.self, swizzleDidSelectSelector)
let didAddMethod = class_addMethod(type(of: delegate), swizzleDidSelectSelector, method_getImplementation(swizzleMethod!), method_getTypeEncoding(swizzleMethod!))
if didAddMethod {
let didSelectOriginalMethod = class_getInstanceMethod(type(of: delegate), NSSelectorFromString("tableView:didSelectRowAt:"))
let didSelectSwizzledMethod = class_getInstanceMethod(type(of: delegate), originalDidSelectSelector)
if didSelectOriginalMethod != nil && didSelectSwizzledMethod != nil {
method_exchangeImplementations(didSelectOriginalMethod!, didSelectSwizzledMethod!)
}
}
}
@objc open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView(tableView, didSelectRowAt: indexPath)
// This is specifically to fix a bug in SwiftUI, where a NavigationLink is
// not de-selecting itself inside a sheet.
tableView.deselectRow(at: indexPath,
animated: true)
}
}
(Original swizzle code is from https://stackoverflow.com/a/59262109/127853), this code sample just adds the deselectRow
call.)
Don't forget to call UITableView.swizzleTableView()
somewhere such as application:didFinishLaunchingWithOptions:
Add the following modifier to your NavigationView to set navigation view style and fix this issue:
.navigationViewStyle(StackNavigationViewStyle())
Explanation:
Default style is DefaultNavigationViewStyle(), from documentation: "The default navigation view style in the current context of the view being styled".
For some reason this will pick up DoubleColumnNavigationViewStyle instead of StackNavigationViewStyle on iPhone, if you set style explicitly it behaves as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With