SwiftUI MVVM Coordinator/Router/NavigationLink
It is better to use generics for your row, as below (tested with Xcode 11.4)
Usage example:
ProductFamilyRow(item: ProductFamilyItem(title: "Test"),
destinationView1: { Text("Details1") },
destinationView2: { Text("Details2") })
Interface:
Update - added block for row highlight. List has auto detection for button or link inside row and highlights if any standard (!key) present. So, to disable such behaviour it needs to hide everything under custom button style.
struct ProductFamilyRowStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.colorMultiply(configuration.isPressed ?
Color.white.opacity(0.5) : Color.white) // any effect you want
}
}
struct ProductFamilyRow: View {
let item: ProductFamilyItem
let destinationView1: () -> D1
let destinationView2: () -> D2
init(item: ProductFamilyItem, @ViewBuilder destinationView1: @escaping () -> D1,
@ViewBuilder destinationView2: @escaping () -> D2)
{
self.item = item
self.destinationView1 = destinationView1
self.destinationView2 = destinationView2
}
@State private var selection: Int? = 0
var body: some View {
VStack {
HStack {
Text(item.title)
Button(action: {
self.selection = 1
}) {
Text("Destination 1")
.background( // hide link inside button !!
NavigationLink(destination: destinationView1(),
tag: 1, selection: self.$selection) { EmptyView() }
)
}.foregroundColor(Color.blue)
Button(action: {
self.selection = 2
}) {
Text("Destination 2")
.background(
NavigationLink(destination: destinationView2(),
tag: 2, selection: self.$selection) { EmptyView() }
)
}.foregroundColor(Color.blue)
}
//Image(item.image)
}.frame(maxWidth: .infinity) // to have container centered
.buttonStyle(ProductFamilyRowStyle())
}
}
In MVVM + Coordinator, how to deal with sub view?
When the ground view receives the tap, it tells the ground view model.
- The ground view model tells the ground coordinator.
- The ground coordinator tells the current detail coordinator (if there is one) to dismiss.
- The current detail coordinator dismisses its view.
- The ground coordinator creates a new detail coordinator.
- The ground coordinator tells the new detail coordinator to present.
- The new detail coordinator creates a detail view model and detail
view. It passes the detail view model to the detail view. - The detail coordinator presents the detail view.
There are some variations in exactly when items are created and destroyed, but the above is the general idea.
Need help getting NavigationLink to work in SwiftUI
Your List
is iterating over results
which is [User]
, so item
is a User
and that should be passed to UserView()
which is expecting a single User
, not the array of User
s.
var body: some View {
NavigationView {
List(results, id: \.id) { item in
NavigationLink(destination: UserView(results: item)) { // here
VStack(alignment: .leading) {
Text(item.name)
.font(.headline)
Text("Age: \(item.age)")
.foregroundColor(Color.red)
}
}
}
.onAppear(perform: loadData)
}
}
I think it has something to do with the UserView_Previews, but I am not sure.
The User_Previews
is only unit test data that allows you to test your User
View
in the Preview Pane in Xcode. It isn't used when you build.
SwiftUI ViewModifier not working as a NavigationLink
The modifier doesn't work because the content
argument is not the actual view being modified, but instead is a proxy:
content is a proxy for the view that will have the modifier represented by Self applied to it.
Reference.
This is what a quick debugging over the modifier shows:
(lldb) po content
SwiftUI._ViewModifier_Content()
As the proxy is an internal type of SwiftUI, we can't know for sure why NavigationLink
doesn't work with it.
A workaround would be to skip the modifier, and only add the extension over View
:
extension View {
func navLink(title: String) -> some View {
NavigationLink(destination: content) {
Text(title)
}
}
}
Related Topics
Uigesturerecognizer and Uitableviewcell Issue
Customizing the More Menu on a Tab Bar
What's the Difference Between All the Selection Segues
Automatic Preferred Max Layout Width Is Not Available on iOS Versions Prior to 8.0
Error When Adding Input View to Textfield iOS 8
Swift Different Images For Annotation
Swift Compiler Shows Expected Declaration Error
Xcode Beta 6 iOS 8: Simulator Not Working
Does Apple Provide an API for Siri
How to Implement the Hashable Protocol in Swift for an Int Array (A Custom String Struct)
Workaround on the Threads Limit in Grand Central Dispatch
Volunteermatch API Objective C
Uibutton Image Behavior Changed in iOS 15
Uistackview Hide View Animation
How to Combine React Native with Socket.Io