表单/表格中的 SwiftUI 多个 NavigationLink - 条目保持突出显示
Posted
技术标签:
【中文标题】表单/表格中的 SwiftUI 多个 NavigationLink - 条目保持突出显示【英文标题】:SwiftUI multiple NavigationLinks in Form/Sheet - entry stays highlighted 【发布时间】:2020-09-17 19:33:34 【问题描述】:我遇到了 Xcode 12 / ios 14 的问题。在带有 NavigationView 的工作表中使用多个 NavigationLink 会导致 NavigationLink 条目在返回页面后保持突出显示。这不仅是模拟器的问题。请参阅随附的 GIF:
有人知道如何解决这个问题吗?
类似问题:SwiftUI - NavigationLink cell in a Form stays highlighted after detail pop(但这不是这里的问题)。
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")
【问题讨论】:
看起来像sheet
中的一个错误 - 没有它也可以正常工作。您可以向 Apple 提交错误报告。
终于没有遇到取模的bug (i % 2) == 0 not working :))))))))))))))))) 我笑了河流:)
天哪,是的,我提交了一个错误报告。希望这会很快得到解决。
我最终完全重新实现了表单。
【参考方案1】:
在工作表中使用NavigationLink
时,我也遇到了这个问题。我在 iOS 14 上的解决方案过于调侃didSelectRowAt:
或UITableView
。选择该行时,我取消选择它。有更多代码用于检测它是否在工作表中等,但这是基本的,让它工作代码:
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)
(原始 swizzle 代码来自 https://***.com/a/59262109/127853),此代码示例只是添加了 deselectRow
调用。)
别忘了给UITableView.swizzleTableView()
打电话,比如application:didFinishLaunchingWithOptions:
【讨论】:
这对我来说在 iPad 上崩溃了,在 iPhone 上它工作正常。你有过类似的经历吗? @dehlen 我在nsh_set
方法中添加了额外的代码来检测委托是否是 SwiftUI 类,如果是,则只替换该方法,因为我在非 swiftUI 代码上遇到问题(而且它是非 SwiftUI 代码不需要)。我正在apps.apple.com/app/appwage/id834352667#?platform=iphone 中积极使用此代码。
首先感谢您回复我并与我们分享您的解决方案。在 iPhone 上,这对我有用。但是在 iPad 上运行它会导致无限循环,最终导致应用程序崩溃。由于我无法在评论中上传屏幕截图,因此这里有一个显示调试器的链接。如您所见,它在运行didSelectRow
的原始实现时崩溃。这是在任何运行 14.2 和 Xcode 12.2.0 的 iPad 上:cln.sh/ryVMcw【参考方案2】:
将以下修饰符添加到您的 NavigationView 以设置导航视图样式并修复此问题:
.navigationViewStyle(StackNavigationViewStyle())
解释:
默认样式是 DefaultNavigationViewStyle(),来自文档:“当前正在设置样式的视图上下文中的默认导航视图样式”。
由于某种原因,这将在 iPhone 上使用 DoubleColumnNavigationViewStyle 而不是 StackNavigationViewStyle,如果您明确设置样式,它会按预期运行。
【讨论】:
不是每个人都想在 iPad 上使用 iPhone 布局。 提到的问题是,根据我的经验,特定于 iPhone,如果您需要在 iPadOS 上支持 StackNavigationViewStyle,您可以有条件地设置此样式。 我明白了。很有趣。以上是关于表单/表格中的 SwiftUI 多个 NavigationLink - 条目保持突出显示的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 将 navigationBarItems 按钮与“消息”中的大 navigationBarTitle 对齐