除了导航到另一个视图之外,NavigationLink 是否还可以执行其他操作?

问题描述 投票:0回答:6

我正在尝试创建一个按钮,它不仅可以导航到另一个视图,而且可以同时运行一个函数。我尝试将 NavigationLink 和按钮嵌入到堆栈中,但我只能单击按钮。

ZStack {
    NavigationLink(destination: TradeView(trade: trade)) {
        TradeButton()
    }
    Button(action: {
        print("Hello world!") //this is the only thing that runs
    }) {
        TradeButton()
    }
}
swiftui
6个回答
98
投票

您可以使用 .simultaneousGesture 来做到这一点。 NavigationLink 将进行导航,同时执行完全按照您想要的操作:

NavigationLink(destination: TradeView(trade: trade)) {
    Text("Trade View Link")
}.simultaneousGesture(TapGesture().onEnded {
    print("Hello world!")
})

注意:这个答案是我刚接触 SwiftUI 时写的。我不再使用这种技术,因为我认为这是一个非常老套的解决方案。如果您的用例绝对需要它,您仍然可以使用它,但如果需要,请仔细测试您的应用程序。正如其他人提到的,这种技术在列表中不起作用。


15
投票

您可以使用 NavigationLink(destination:isActive:label:)。使用绑定上的 setter 来了解链接何时被点击。我注意到可以在内容区域之外点击 NavigationLink,并且这种方法也可以捕获这些点击。

struct Sidebar: View {
    @State var isTapped = false

    var body: some View {
        NavigationLink(destination: ViewToPresent(),
                       isActive: Binding<Bool>(get: { isTapped },
                                               set: { isTapped = $0; print("Tapped") }),
                       label: { Text("Link") })
    }
}

struct ViewToPresent: View {
    var body: some View {
        print("View Presented")
        return Text("View Presented")
    }
}

我唯一注意到的是设置器触发了三次,其中一次是在它被呈现之后。这是输出:

Tapped
Tapped
View Presented
Tapped

11
投票

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
    }
}

9
投票

这对我的自动取款机有用:

@State private var isActive = false

NavigationLink(destination: MyView(), isActive: $isActive) {
    Button {
        // run your code
        
        // then set
        isActive = true

    } label: {
        Text("My Link")
    }
}

5
投票

使用 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属性。

(它在列表中工作)


-4
投票

我也刚刚用过:

NavigationLink(destination: View()....) { 
    Text("Demo")
}.task { do your stuff here }

iOS 15.3 部署目标。

© www.soinside.com 2019 - 2024. All rights reserved.