SwiftUI 工作表中未触发深层链接 onChange
Posted
技术标签:
【中文标题】SwiftUI 工作表中未触发深层链接 onChange【英文标题】:Deep link onChange not triggered in SwiftUI sheet 【发布时间】:2020-10-08 08:19:52 【问题描述】:我的 SwiftUI 应用中的深层链接存在问题。
在我的应用程序类中,我已将 deepLink 声明为层次结构中 ContentView() 下每个视图的环境变量:
...
@main
struct TestApp: App
var userSettings: UserSettings
var dataFetcher: DataFetcher
var dataUpdater: DataUpdater
@State var deepLink = ""
init()
userSettings = UserSettings()
dataFetcher = DataFetcher(userSettings: userSettings)
dataUpdater = DataUpdater(userSettings: userSettings)
var body: some Scene
WindowGroup
ContentView()
.environmentObject(userSettings)
.environmentObject(dataFetcher)
.environmentObject(dataUpdater)
.onOpenURL url in
deepLink = url.absoluteString
.environment(\.deepLink, deepLink)
在我的 ContentView() 中,我将 deepLink 声明为环境变量
struct ContentView: View
...
@State var isTestSheetViewPresented = false
@Environment(\.deepLink) var deepLink: String
...
var body: some View
Button(action:
self.isTestSheetViewPresented = true
, label:
HStack
Spacer()
Image(systemName: "plus")
Text("Add")
Spacer()
)
.sheet(isPresented: $isTestSheetViewPresented, content:
TestSheetView(isPresented: self.$isTestSheetViewPresented)
)
.onChange(of: self.deepLink) _ in
self.isTestSheetViewPresented = true
而TestSheetView是这样的
struct TestSheetView: View
@Environment(\.deepLink) var deepLink: String
@State var url: String = ""
var body: some View
Text(url)
.onChange(of: deepLink) _ in
if deepLink != ""
self.url = deepLink
问题是,当我点击一个链接并打开我的应用程序时,TestSheetView 会正确显示,但除非我向下滚动一点,否则不会触发 onChange。
相反,如果我将 TestSheetView 的相同代码放在 ContentView 中,则文本会正确显示
【问题讨论】:
似乎是时间问题。在初始化TestSheetView
时,body
是在 deepLink
更改之后创建的,因此它无法检测到它。解决方案可能是您在TestSheetView
中使用onAppear
并从那里读取,或者您从ContentView
传入deepLink
。如果您需要完整的解决方案,请告诉我。
@George_E 啊,是时间问题。添加 onAppear() 修复它!如果您想发布答案,我会将其标记为解决方案。谢谢
谢谢 - 也只是一个小评论,而不是deepLink != ""
,最好使用!deepLink.isEmpty
。不仅仅是为了可读性,还有性能,虽然差别不会很大。
【参考方案1】:
似乎是时间问题。在初始化 TestSheetView
时,主体是在 deepLink
更改之后创建的,因此它无法检测到它。
解决方案是在TestSheetView
中使用onAppear
并从那里读取,如下所示:
struct TestSheetView: View
@Environment(\.deepLink) var deepLink: String
@State var url: String = ""
var body: some View
Text(url)
.onAppear
if deepLink != ""
self.url = deepLink
【讨论】:
【参考方案2】:同时处理视图尚未出现的情况和链接正在视图中导航的情况都是不符合人体工程学的。以下视图修饰符处理这两种情况。它假定***导航视图中的 .onOpenURL() 处理程序设置当前选项卡选择以及 currentDeepLink 环境值。
struct DeepLinkViewModifier: ViewModifier
@Environment(\.currentDeepLink) private var currentDeepLink
let action: ((URL) -> Bool)
func body(content: Content) -> some View
content
.onAppear
if let url = currentDeepLink.wrappedValue,
action(url)
currentDeepLink.wrappedValue = nil
.onOpenURL url in
_ = action(url)
extension View
func onDeepLink(perform action: @escaping ((URL) -> Bool)) -> some View
return self.modifier(DeepLinkViewModifier(action: action))
用途:
struct SomeView: View
@State urlString: String = ""
var body: some View
Text(urlString).onDeepLink url
self.string = url.absoluteString
return true // return false if another handler should consume
struct ContentView: View
@State private var tabSelection: TabSelection = .something
@State private var currentDeepLink: URL? = nil
var body: some View
TabView(selection: self.$tabSelection)
...
.onOpenURL url in
self.tabSelection = ... // determine selection from URL
self.currentDeepLink = url
.environment(\.tabSelection, self.$tabSelection)
.environment(\.currentDeepLink, self.$currentDeepLink)
【讨论】:
谢谢,我试试看。但是,非常聪明的解决方案! 仅供参考,我确实在让它可靠地工作时遇到了一些麻烦,有时两个处理程序都会被调用。最后,我发现最好在当前选项卡中处理 URL。此外,您需要检查当前视图是否显示和/或可见,以避免触发多个 onOpenURL 处理程序。以上是关于SwiftUI 工作表中未触发深层链接 onChange的主要内容,如果未能解决你的问题,请参考以下文章
当 ObservedObject 更改时,在 SwiftUI 视图中未调用 onReceive
已发布/观察到的 var 在视图 swiftui 中未更新,带有调用函数