除了导航到另一个视图之外,NavigationLink 是否可以执行操作?
Is it possible for a NavigationLink to perform an action in addition to navigating to another view?
我正在尝试创建一个按钮,它不仅可以导航到另一个视图,而且可以同时 运行 一个功能。我尝试将 NavigationLink 和 Button 都嵌入到 Stack 中,但我只能单击 Button。
ZStack {
NavigationLink(destination: TradeView(trade: trade)) {
TradeButton()
}
Button(action: {
print("Hello world!") //this is the only thing that runs
}) {
TradeButton()
}
}
您可以使用 .simultaneousGesture 来做到这一点。 NavigationLink 将导航并同时执行与您想要的完全相同的操作:
NavigationLink(destination: TradeView(trade: trade)) {
Text("Trade View Link")
}.simultaneousGesture(TapGesture().onEnded{
print("Hello world!")
})
使用 NavigationLink(_:destination:tag:selection:) 初始化器并将模型的 属性 作为 selection 参数传递。因为它是双向绑定,你可以为这个 属性 定义 didset 观察者,然后在那里调用你的函数。
struct ContentView: View {
@EnvironmentObject var navigationModel: NavigationModel
var body: some View {
NavigationView {
List(0 ..< 10, id: \.self) { row in
NavigationLink(destination: DetailView(id: row),
tag: row,
selection: self.$navigationModel.linkSelection) {
Text("Link \(row)")
}
}
}
}
}
struct DetailView: View {
var id: Int;
var body: some View {
Text("DetailView\(id)")
}
}
class NavigationModel: ObservableObject {
@Published var linkSelection: Int? = nil {
didSet {
if let linkSelection = linkSelection {
// action
print("selected: \(String(describing: linkSelection))")
}
}
}
}
在此示例中,您需要将模型作为环境对象传递给 ContentView:
ContentView().environmentObject(NavigationModel())
在 SceneDelegate 和 SwiftUI 预览中。
模型符合 ObservableObject 协议,属性 必须有一个@Published 属性。
(它在列表中工作)
您可以使用 NavigationLink(destination:isActive:label:)。使用绑定上的 setter 可以知道何时点击 link。我注意到可以在内容区域之外点击 NavigationLink,并且这种方法也可以捕获这些点击。
struct Sidebar: View {
@State var isTapped = false
var body: some View {
NavigationLink(destination: ViewToPresent(),
isActive: Binding<Bool>(get: { isTapped },
set: { isTapped = [=10=]; print("Tapped") }),
label: { Text("Link") })
}
}
struct ViewToPresent: View {
var body: some View {
print("View Presented")
return Text("View Presented")
}
}
我唯一注意到的是 setter 触发了三次,其中一次是在它出现之后。这是输出:
Tapped
Tapped
View Presented
Tapped
NavigationLink
+ isActive
+ onChange(of:)
// part 1
@State private var isPushed = false
// part 2
NavigationLink(destination: EmptyView(), isActive: $isPushed, label: {
Text("")
})
// part 3
.onChange(of: isPushed) { (newValue) in
if newValue {
// do what you want
}
}
这适用于我的 atm:
@State private var isActive = false
NavigationLink(destination: MyView(), isActive: $isActive) {
Button {
// run your code
// then set
isActive = true
} label: {
Text("My Link")
}
}
我也刚用过:
NavigationLink(destination: View()....) {
Text("Demo")
}.task { do your stuff here }
iOS 15.3 部署目标。
我正在尝试创建一个按钮,它不仅可以导航到另一个视图,而且可以同时 运行 一个功能。我尝试将 NavigationLink 和 Button 都嵌入到 Stack 中,但我只能单击 Button。
ZStack {
NavigationLink(destination: TradeView(trade: trade)) {
TradeButton()
}
Button(action: {
print("Hello world!") //this is the only thing that runs
}) {
TradeButton()
}
}
您可以使用 .simultaneousGesture 来做到这一点。 NavigationLink 将导航并同时执行与您想要的完全相同的操作:
NavigationLink(destination: TradeView(trade: trade)) {
Text("Trade View Link")
}.simultaneousGesture(TapGesture().onEnded{
print("Hello world!")
})
使用 NavigationLink(_:destination:tag:selection:) 初始化器并将模型的 属性 作为 selection 参数传递。因为它是双向绑定,你可以为这个 属性 定义 didset 观察者,然后在那里调用你的函数。
struct ContentView: View {
@EnvironmentObject var navigationModel: NavigationModel
var body: some View {
NavigationView {
List(0 ..< 10, id: \.self) { row in
NavigationLink(destination: DetailView(id: row),
tag: row,
selection: self.$navigationModel.linkSelection) {
Text("Link \(row)")
}
}
}
}
}
struct DetailView: View {
var id: Int;
var body: some View {
Text("DetailView\(id)")
}
}
class NavigationModel: ObservableObject {
@Published var linkSelection: Int? = nil {
didSet {
if let linkSelection = linkSelection {
// action
print("selected: \(String(describing: linkSelection))")
}
}
}
}
在此示例中,您需要将模型作为环境对象传递给 ContentView:
ContentView().environmentObject(NavigationModel())
在 SceneDelegate 和 SwiftUI 预览中。
模型符合 ObservableObject 协议,属性 必须有一个@Published 属性。
(它在列表中工作)
您可以使用 NavigationLink(destination:isActive:label:)。使用绑定上的 setter 可以知道何时点击 link。我注意到可以在内容区域之外点击 NavigationLink,并且这种方法也可以捕获这些点击。
struct Sidebar: View {
@State var isTapped = false
var body: some View {
NavigationLink(destination: ViewToPresent(),
isActive: Binding<Bool>(get: { isTapped },
set: { isTapped = [=10=]; print("Tapped") }),
label: { Text("Link") })
}
}
struct ViewToPresent: View {
var body: some View {
print("View Presented")
return Text("View Presented")
}
}
我唯一注意到的是 setter 触发了三次,其中一次是在它出现之后。这是输出:
Tapped
Tapped
View Presented
Tapped
NavigationLink
+ isActive
+ onChange(of:)
// part 1
@State private var isPushed = false
// part 2
NavigationLink(destination: EmptyView(), isActive: $isPushed, label: {
Text("")
})
// part 3
.onChange(of: isPushed) { (newValue) in
if newValue {
// do what you want
}
}
这适用于我的 atm:
@State private var isActive = false
NavigationLink(destination: MyView(), isActive: $isActive) {
Button {
// run your code
// then set
isActive = true
} label: {
Text("My Link")
}
}
我也刚用过:
NavigationLink(destination: View()....) {
Text("Demo")
}.task { do your stuff here }
iOS 15.3 部署目标。