I listened by @sonle to using NavigationStack. I think something is going wrong. It does navigate but not like my expecting to destination to Travel Detail. It looks like this.
NavigationLink(destination: {
TravelDetail(TourID: item.id)
}, label: {
TourItemView(tableItem: item)
})
------------THE QUESTION ------------
I have a ScrollView whose content is generated by ForEach parsing the elements in the struct Array. I hope that clicking on different cells will lead to a Detail page and load the information of the corresponding objects. How can I achieve this?
I wrap the style of each cell in a button and plan to perform the page change action through the button click event. At the same time, I retrieve the id of the element in the list page and load the content into the Detail page after jumping to the page. I try to use NavigationView is used to jump, but the placement of NavigationLink confuses me. I want to know if this is a normal method.
I think this is a basic question, but I am stumped. As you can see, I am a beginner, so if you have any reference methods, please provide it to me. Thank you very much!
And if is there a need to provide other parts of the code, please let me know.
List Page:
import SwiftUI
struct ContentView: View {
var tableItems: [TableItem]
init() {
var items = [TableItem]()
for index in 0..<tour.count {
let tourItem = [tour[index]]
let userItem = [user[index]]
let tableItem = TableItem(tourItem: tourItem, user: userItem)
items.append(tableItem)
}
self.tableItems = items
}
var body: some View {
NavigationView {
VStack {
ScrollView(.vertical){
VStack(spacing: 8){
ForEach(tableItems, id: \.id) { item in
Button(action: {
}) {
TourItemView(tableItem: item)
}//ButtonStyle
}//ForEach
}//VStack
}//ScrollView
}//VStack
.padding()
}//NavigationView
}//view
}//ContentView
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Detail Page:
import SwiftUI
struct TravelDetail: View {
//let DetailItem: TravelDetailConstant
var ItemID: String
var result: TravelDetailConstant?
init(TourID: String) {
self.ItemID = TourID
result = initializersTourItem(id: ItemID)
}
func initializersTourItem(id: String)-> TravelDetailConstant {
guard let register = ContentView().tableItems.first(where: { $0.id == id }),
let initTour = tour.first(where: { $0.id == id }),
let initUser = user.first(where: { $0.id == initTour.mainKeeper })
else {
return TravelDetailConstant(
imagetext: "",
title: "",
startTime: "",
finishTime: "",
place: "",
peopleNum: "",
detailLocaltion: "",
meetingPlace: "",
tag: nil,
detailContent: "",
userImage: "",
userNikename: "",
userGender: "",
userBadge: []
)
}
let detail = TravelDetailConstant(imagetext: register.tourImage, title: register.title, startTime: register.startTime, finishTime: initTour.finishTime, place: register.location, peopleNum: register.peopeleNum, detailLocaltion: initTour.detailLocaltion, meetingPlace: initTour.meetingPlace, tag: register.tag, detailContent: initTour.detailContent, userImage: register.userImage, userNikename: register.userName, userGender: initUser.userGender, userBadge: initUser.userBadge)
return detail
}
var body: some View {
VStack{
Spacer()
.frame(height: 20)
HStack{
Image((result?.userImage)!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 75, height: 75)
.clipShape(Circle())
.background(
Circle()
.padding(-2)
.foregroundColor(Color("DesignLightMutedOrange"))
)
.padding(.leading, 15)
VStack{
HStack{
Text((result?.userNikename)!)
.frame(width: 186, height: 28)
.padding(.trailing, 12)
Image((result?.userGender)!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 24, height: 24)
}
.padding(.bottom, 4)
ScrollView(.horizontal) {
Button(action: {}) {
Image("")
}
}
.frame(width: 186, height: 28)
}
Button(action: { }) {
Image("heart")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 24, height: 24)
.padding(.trailing, 15)
}
}
Spacer().frame(height: 20)
HStack{
Button(action: {
}){
Text("Detail")
}
.frame(width: 150, height: 52, alignment: .leading)
.background(Color .red)
.padding(.leading, 0)
Button(action: {
}){
Text("Q&A")
}
.frame(width: 150, height: 52, alignment: .leading)
.background(Color .gray)
.listRowInsets(EdgeInsets())
Spacer()
}
Spacer()
}
}
}
struct TravelDetail_Previews: PreviewProvider {
static var previews: some View {
TravelDetail(TourID: "")
}
}
Since NavigationView was deprecated, I suggest using NavigationStack instead. Something like:
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack {
....
//Other stuff
Button(action: {
path.append(item)
}, label: {
TourItemView(tableItem: item)
})
//OR
//NavigationLink(value: item) {
// TourItemView(tableItem: item)
//}
}
.navigationDestination(for: TableItem.self) { item in
TourItemView(tableItem: item)
}
}
}
}
Your TableItem
model needs to fully conform to Hashable
protocol.
struct TableItem: Hashable {
...
}