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. struct Landmark: Hashable, Codable, Identifiable {
  4. var id: Int
  5. var name: String
  6. fileprivate var imageName: String
  7. fileprivate var coordinates: Coordinates
  8. var state: String
  9. var park: String
  10. var category: Category
  11. var locationCoordinate: CLLocationCoordinate2D {
  12. CLLocationCoordinate2D(
  13. latitude: coordinates.latitude,
  14. longitude: coordinates.longitude)
  15. }
  16. }
  17. extension Landmark {
  18. var image: Image {
  19. ImageStore.shared.image(name: imageName)
  20. }
  21. }
  22. struct Coordinates: Hashable, Codable {
  23. var latitude: Double
  24. var longitude: Double
  25. }
Step 4 - Set Up Navigation between List and Detail
  1. import SwiftUI
  2. struct LandmarkList: View {
  3. var body: some View {
  4. NavigationView{
  5. List(landmarkData){ dataObj in
  6. NavigationLink(destination: LandmarkDetail(landmark: dataObj)) {
  7. LandmarkRow(landmark: dataObj)
  8. }
  9. }
  10. .navigationBarTitle(Text("Landmarks"), displayMode: .large)
  11. }
  12. }
  13. }
  14. #if DEBUG
  15. struct LandmarkList_Previews: PreviewProvider {
  16. static var previews: some View {
  17. LandmarkList()
  18. }
  19. }
  20. #endif
Note
You need to set up a root view on sceneDelegate.
App screenshot