Lists And Navigation In SwiftUI

Here, we will implement a TableView list and navigation with the help of SwiftUI.

List

A container that presents rows of data arranged in a single column.
 
SwiftUI's List is similar to UITableView in which you can show static or dynamic TableView cells as per your app need. However, it is simple to use, we don't need to create prototype cells in storyboards, or register them in code. We don't need to tell how many rows in a cell are there and we don't need to dequeue and configure cells.
 
Instead, SwiftUIs are designed for composability - SwiftUI has us build small views that know how to configure themselves as list rows, then use those. 
 
Example 
 
Landmark.swift declares a landmarks structure that stores all of the landmark information that the app needs to display, and that imports an array of landmark data from landmarkData.json. 
 
Step 1 
  1. [  
  2.     {  
  3.         "name": "Turtle Rock",  
  4.         "category": "Featured",  
  5.         "city": "Twentynine Palms",  
  6.         "state": "California",  
  7.         "id": 1001,  
  8.         "park": "Joshua Tree National Park",  
  9.         "coordinates": {  
  10.             "longitude": -116.166868,  
  11.             "latitude": 34.011286  
  12.         },  
  13.         "imageName": "turtlerock"  
  14.     },  
  15.     {  
  16.         "name": "Silver Salmon Creek",  
  17.         "category": "Lakes",  
  18.         "city": "Port Alsworth",  
  19.         "state": "Alaska",  
  20.         "id": 4,  
  21.         "park": "Lake Clark National Park and Preserve",  
  22.         "coordinates": {  
  23.             "longitude": -152.665167,  
  24.             "latitude": 59.980167  
  25.         },  
  26.         "imageName": "silversalmoncreek"  
  27.     }  
  28. ]  
Step 2 - Create a Landmark Row
 
Here, we created a list landmark custom row which contains an image and text.
  1. import SwiftUI  
  2. struct LandmarkRow: View {  
  3.     var landmark: Landmark  
  4.     var body: some View {  
  5.         HStack {  
  6.             landmark.image  
  7.             .resizable()  
  8.             .frame(width: 50, height: 50)  
  9.             Text(verbatim: landmark.name)  
  10.             Spacer()  
  11.         }  
  12.     }  
  13. }  
  14. #if DEBUG  
  15. struct LandmarkRow_Previews: PreviewProvider {  
  16.     static var previews: some View {  
  17.         Group {  
  18.             LandmarkRow(landmark: landmarkData[0])  
  19.         }  
  20.         .previewLayout(.fixed(width: 300, height: 70))  
  21.     }  
  22. }  
  23. #endif  
In the above code of LandmarkRow_Previews, update the landmark parameter to be the second element in the landmarkData array.
 
Use the previewLayout(_: ) modifier to set a size that approximates a row in a list.
 
You can use a Group to return multiple previews from the preview provider.
  
Step 3 - Make the list Dynamic
  1. import SwiftUI  
  2. import CoreLocation  
  3.   
  4. struct Landmark: Hashable, Codable, Identifiable {  
  5.     var id: Int  
  6.     var name: String  
  7.     fileprivate var imageName: String  
  8.     fileprivate var coordinates: Coordinates  
  9.     var state: String  
  10.     var park: String  
  11.     var category: Category  
  12.     var locationCoordinate: CLLocationCoordinate2D {  
  13.         CLLocationCoordinate2D(  
  14.             latitude: coordinates.latitude,  
  15.             longitude: coordinates.longitude)  
  16.     }  
  17. }  
  18. extension Landmark {  
  19.     var image: Image {  
  20.         ImageStore.shared.image(name: imageName)  
  21.     }  
  22. }  
  23. struct Coordinates: Hashable, Codable {  
  24.     var latitude: Double  
  25.     var longitude: Double  
Step 4 - Set Up Navigation between List and Detail
  1. import SwiftUI  
  2.   
  3. struct LandmarkList: View {  
  4.     var body: some View {  
  5.         NavigationView{  
  6.             List(landmarkData){ dataObj in  
  7.                 NavigationLink(destination: LandmarkDetail(landmark: dataObj)) {  
  8.                     LandmarkRow(landmark: dataObj)  
  9.                 }  
  10.             }  
  11.             .navigationBarTitle(Text("Landmarks"), displayMode: .large)  
  12.         }  
  13.     }  
  14. }  
  15. #if DEBUG  
  16. struct LandmarkList_Previews: PreviewProvider {  
  17.     static var previews: some View {  
  18.             LandmarkList()  
  19.     }  
  20. }  
  21. #endif  
Note
You need to set up a root view on sceneDelegate.
 
 
App screenshot