Reputation: 196
I'm trying to make an app using Apple's SwiftUI and I need to have two buttons that present two different views in a single List
row.
I use Xcode beta 7 and MacOS Catalina beta 7. I've tried to add a Button
that present the view but, I couldn't click it and when I tried on a simple Button
outside the List
and clicked it, the AddList()
view didn't appear. I've also tried adding a navigationButton
inside navigationButton
but it didn't work too. Adding a tapAction
doesn't work too when you click on it, the view still does not appear
NavigationView {
List(0..<5) { item in
NavigationLink(destination: ContentOfList()) {
Text("hello") // dummy text
Spacer()
Text("edit")
.tapAction {
AddList() // This is the view I want to present
}
}
}.navigationBarItems(trailing: NavigationLink(destination: AddList(), label: { // doesn't work within navigationBarItems
Image(systemName: "plus.circle.fill")
}))
}
I expect the AddList()
view to appear but in the two cases, it doesn't.
Upvotes: 6
Views: 20340
Reputation: 8266
Much improved version (SwiftUI, iOS 13 beta 7)
The same solution works for dismissing Modals presented with the .sheet modifier.
import SwiftUI
struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
Button(
"Here is Detail View. Tap to go back.",
action: { self.presentationMode.wrappedValue.dismiss() }
)
}
}
struct RootView: View {
var body: some View {
VStack {
NavigationLink(destination: DetailView())
{ Text("I am Root. Tap for Detail View.") }
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
RootView()
}
}
}
Upvotes: 7
Reputation: 40489
Update: The NavigationButton was very short lived. In beta3 it is already deprecated. I am updating the code to use its replacement: NavigationLink.
You can present a view from all three places. Here's how:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
TopView().navigationBarTitle(Text("Top View"))
}
}
}
struct TopView: View {
@State private var viewTypeA = true
let detailViewA = DynamicNavigationDestinationLink(id: \String.self) { data in
ListA(passedData: data)
}
let detailViewB = DynamicNavigationDestinationLink(id: \String.self) { data in
ListB(passedData: data)
}
var body: some View {
List(0..<5) { item in
NavigationLink(destination: ListC(passedData: "FROM ROW #\(item)")) {
HStack {
Text("Row #\(item)")
Spacer()
Text("edit")
.tapAction {
self.detailViewA.presentedData?.value = "FROM TAP ACTION Row #\(item)"
}
}
}
}.navigationBarItems(trailing: Button(action: {
self.detailViewB.presentedData?.value = "FROM PLUS CIRCLE"
}, label: {
Image(systemName: "plus.circle.fill")
}))
}
}
struct ListA: View {
let passedData: String
var body: some View {
VStack {
Text("VIEW A")
Text(passedData)
}
}
}
struct ListB: View {
let passedData: String
var body: some View {
VStack {
Text("VIEW B")
Text(passedData)
}
}
}
struct ListC: View {
let passedData: String
var body: some View {
VStack {
Text("VIEW C")
Text(passedData)
}
}
}
Upvotes: 5
Reputation: 838
improved version. (Swift, iOS 13 beta 4)
class NavigationModel : BindableObject {
var willChange = PassthroughSubject<Void, Never>()
var presentedData: String? {
didSet {
willChange.send()
}
}
func dismiss() { if presentedData != nil {
presentedData = nil
} }
}
struct ContentView: View {
var body: some View {
NavigationView {
MasterView()
}.environmentObject(NavigationModel())
}
}
struct MasterView: View {
@EnvironmentObject
var navigationModel: NavigationModel
var destinationLink = DynamicNavigationDestinationLink<String, String, DetailView>(id: \.self) { data in DetailView(data: data) }
var body: some View {
List(0..<10) { index in
Button("I am root. Tap for more details of #\(index).") {
self.navigationModel.presentedData = "#\(index)"
}
}
.navigationBarTitle("Master")
.onReceive(navigationModel.willChange) {
self.destinationLink.presentedData?.value = self.navigationModel.presentedData
}
}
}
struct DetailView: View {
@EnvironmentObject
var model: NavigationModel
let data: String
var body: some View {
Button("Here are details of \(data). Tap to go back.") {
self.model.dismiss()
}
.navigationBarTitle("Detail \(data)")
}
}
struct Empty : Hashable {
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
Upvotes: 1