設置基本地標詳細信息視圖後,您須要爲用戶提供查看完整地標列表以及查看每一個位置詳細信息的方法。html
您將建立可顯示有關任何地標的信息的視圖,並動態生成滾動列表,用戶能夠點按該列表以查看地標的詳細視圖。要微調UI,您將使用Xcode的畫布以不一樣的設備大小呈現多個預覽。git
下載項目文件以開始構建此項目,並按照如下步驟操做。github
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-nkltdvxa-q.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★css
設置基本地標詳細信息視圖後,您須要爲用戶提供查看完整地標列表以及查看每一個位置詳細信息的方法。html
您將建立可顯示有關任何地標的信息的視圖,並動態生成滾動列表,用戶能夠點按該列表以查看地標的詳細視圖。要微調UI,您將使用Xcode的畫布以不一樣的設備大小呈現多個預覽。git
下載項目文件以開始構建此項目,並按照如下步驟操做。github
在[SwiftUI教程]二、建立和組合視圖中,您將信息硬編碼到全部自定義視圖中。在這裏,您將學習將數據傳遞到自定義視圖中以供顯示。json
首先下載入門項目並熟悉示例數據。swift
第1步數組
在Project導航器中,選擇Models > Landmark.swift
.微信
Landmark.swift
聲明一種Landmark
結構,存儲應用程序須要顯示的全部地標信息,並從中導入一系列地標數據。landmarkData.json
session
1 import SwiftUI 2 import CoreLocation 3 4 struct Landmark: Hashable, Codable { 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 13 var locationCoordinate: CLLocationCoordinate2D { 14 CLLocationCoordinate2D( 15 latitude: coordinates.latitude, 16 longitude: coordinates.longitude) 17 } 18 19 func image(forSize size: Int) -> Image { 20 ImageStore.shared.image(name: imageName, size: size) 21 } 22 23 enum Category: String, CaseIterable, Codable, Hashable { 24 case featured = "Featured" 25 case lakes = "Lakes" 26 case rivers = "Rivers" 27 } 28 } 29 30 struct Coordinates: Hashable, Codable { 31 var latitude: Double 32 var longitude: Double 33 }
第2步閉包
在Project導航器中,選擇Resources> landmarkData.json
.
您將在本教程的其他部分以及隨後的全部內容中使用此示例數據。
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": 1002, 21 "park": "Lake Clark National Park and Preserve", 22 "coordinates": { 23 "longitude": -152.665167, 24 "latitude": 59.980167 25 }, 26 "imageName": "silversalmoncreek" 27 }, 28 ... 29 ]
第3步
請注意,如今能夠命名建立和組合視圖中的類型。ContentView
LandmarkDetail
您將在此以及如下每一個教程中建立多個視圖類型。
1 import SwiftUI 2 3 struct LandmarkDetail: View { 4 var body: some View { 5 VStack { 6 MapView() 7 .frame(height: 300) 8 9 CircleImage() 10 .offset(y: -130) 11 .padding(.bottom, -130) 12 13 VStack(alignment: .leading) { 14 Text("Turtle Rock") 15 .font(.title) 16 17 HStack(alignment: .top) { 18 Text("Joshua Tree National Park") 19 .font(.subheadline) 20 Spacer() 21 Text("California") 22 .font(.subheadline) 23 } 24 } 25 .padding() 26 27 Spacer() 28 } 29 } 30 } 31 32 struct LandmarkDetail_Preview: PreviewProvider { 33 static var previews: some View { 34 LandmarkDetail() 35 } 36 }
第1步
建立一個名爲的新SwiftUI視圖。LandmarkRow.swift
第2步
若是預覽不可見,請經過選擇Editor > Editor and Canvas來顯示畫布,而後單擊「Get Started」
第3步
添加landmark
爲存儲屬性。LandmarkRow
添加landmark
屬性時,預覽將中止工做,由於類型在初始化期間須要一個標記實例。LandmarkRow
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 Text("Hello World") 8 } 9 } 10 11 struct LandmarkRow_Previews: PreviewProvider { 12 static var previews: some View { 13 LandmarkRow() 14 } 15 }
要修復預覽,您須要修改預覽提供程序。
第4步
在previews
static屬性中,將landmark參數添加到初始值設定項,指定數組的第一個元素。LandmarkRow_Previews
LandmarkRow
landmarkData
預覽顯示文本Hello World。修復後,您能夠爲行構建佈局。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 Text("Hello World") 8 } 9 } 10 11 struct LandmarkRow_Previews: PreviewProvider { 12 static var previews: some View { 13 LandmarkRow(landmark: landmarkData[0]) 14 } 15 }
第5步
將現有文本視圖嵌入到HStack
。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 Text("Hello World") 9 } 10 } 11 } 12 13 struct LandmarkRow_Previews: PreviewProvider { 14 static var previews: some View { 15 LandmarkRow(landmark: landmarkData[0])
第6步
修改文本視圖以使用landmark
屬性name
。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 Text(landmark.name) 9 } 10 } 11 } 12 13 struct LandmarkRow_Previews: PreviewProvider { 14 static var previews: some View { 15 LandmarkRow(landmark: landmarkData[0]) 16 } 17 }
第7步
經過在文本視圖以前添加圖像來完成行。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 landmark.image(forSize: 50) 9 Text(landmark.name) 10 } 11 } 12 } 13 14 struct LandmarkRow_Previews: PreviewProvider { 15 static var previews: some View { 16 LandmarkRow(landmark: landmarkData[0]) 17 } 18 }
Xcode的畫布自動識別並顯示當前編輯器中符合協議的任何類型。預覽提供程序返回一個或多個視圖,其中包含用於配置大小和設備的選項。PreviewProvider
您能夠從預覽提供程序自定義返回的內容,以準確呈現對您最有幫助的預覽。
第1步
在將參數更新爲數組中的第二個元素。LandmarkRow_Previews
landmark
landmarkData
預覽當即更改以顯示第二個樣本地標而不是第一個。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 landmark.image(forSize: 50) 9 Text(landmark.name) 10 } 11 } 12 } 13 14 struct LandmarkRow_Previews: PreviewProvider { 15 static var previews: some View { 16 LandmarkRow(landmark: landmarkData[1]) 17 } 18 }
第2步
使用修飾符設置近似列表中行的大小。previewLayout(_:)
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 landmark.image(forSize: 50) 9 Text(landmark.name) 10 } 11 } 12 } 13 14 struct LandmarkRow_Previews: PreviewProvider { 15 static var previews: some View { 16 LandmarkRow(landmark: landmarkData[1]) 17 .previewLayout(.fixed(width: 300, height: 70)) 18 } 19 }
第3步
將返回的行換行Group
,而後再將第一行添加回來。
Group
是用於對視圖內容進行分組的容器。Xcode將組的子視圖渲染爲畫布中的單獨預覽。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 landmark.image(forSize: 50) 9 Text(landmark.name) 10 } 11 } 12 } 13 14 struct LandmarkRow_Previews: PreviewProvider { 15 static var previews: some View { 16 Group { 17 LandmarkRow(landmark: landmarkData[0]) 18 .previewLayout(.fixed(width: 300, height: 70)) 19 LandmarkRow(landmark: landmarkData[1]) 20 .previewLayout(.fixed(width: 300, height: 70)) 21 } 22 } 23 }
第4步
要簡化代碼,請將調用移至組的子聲明外部。previewLayout(_:)
視圖的子項繼承視圖的上下文設置,例如預覽配置。
1 import SwiftUI 2 3 struct LandmarkRow: View { 4 var landmark: Landmark 5 6 var body: some View { 7 HStack { 8 landmark.image(forSize: 50) 9 Text(landmark.name) 10 } 11 } 12 } 13 14 struct LandmarkRow_Previews: PreviewProvider { 15 static var previews: some View { 16 Group { 17 LandmarkRow(landmark: landmarkData[0]) 18 LandmarkRow(landmark: landmarkData[1]) 19 } 20 .previewLayout(.fixed(width: 300, height: 70)) 21 } 22 }
您在預覽提供程序中編寫的代碼僅更改Xcode在畫布中顯示的內容。因爲該#if DEBUG
指令,編譯器會刪除代碼,所以它不會隨您的應用程序一塊兒提供。
List
類型時,能夠顯示特定於平臺的視圖列表。列表的元素能夠是靜態的,就像您目前建立的堆棧的子視圖同樣,或者是動態生成的。您甚至能夠混合靜態和動態生成的視圖。
第1步
建立一個名爲的新SwiftUI視圖。LandmarkList.swift
第2步
Text
用a 替換默認視圖List
,並提供帶有前兩個標記的實例做爲列表的子標記。LandmarkRow
預覽顯示以適合iOS的列表樣式呈現的兩個地標。
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 List { 6 LandmarkRow(landmark: landmarkData[0]) 7 LandmarkRow(landmark: landmarkData[1]) 8 } 9 } 10 } 11 12 struct LandmarkList_Previews: PreviewProvider { 13 static var previews: some View { 14 LandmarkList() 15 } 16 }
您能夠直接從集合中生成行,而不是單獨指定列表的元素。
您能夠經過傳遞數據集合以及爲集合中的每一個元素提供視圖的閉包來建立顯示集合元素的列表。該列表使用提供的閉包將集合中的每一個元素轉換爲子視圖。
第1步
刪除兩個靜態地標行,而後傳遞給初始化程序。landmarkData
List
列表使用可識別的數據。您能夠經過如下兩種方式之一來識別數據:經過identified(by:)
使用惟一標識每一個元素的屬性的鍵路徑調用方法,或者使數據類型符合Identifiable
協議。
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 List(landmarkData.identified(by: \.id)) { landmark in 6 7 } 8 } 9 } 10 11 struct LandmarkList_Previews: PreviewProvider { 12 static var previews: some View { 13 LandmarkList() 14 } 15 }
第2步
經過從閉包返回a 來完成動態生成的列表。LandmarkRow
這爲數組中的每一個元素建立一個。LandmarkRow
landmarkData
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 List(landmarkData.identified(by: \.id)) { landmark in 6 LandmarkRow(landmark: landmark) 7 } 8 } 9 } 10 11 struct LandmarkList_Previews: PreviewProvider { 12 static var previews: some View { 13 LandmarkList() 14 } 15 }
接下來,您將List
經過添加Identifiable
對Landmark
類型的一致性來簡化代碼。
第3步
切換到並聲明符合協議。Landmark.swift
Identifiable
因爲該Landmark
類型已經具備協議id
所需的屬性Identifiable
,所以沒有其餘工做要作。
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 13 var locationCoordinate: CLLocationCoordinate2D { 14 CLLocationCoordinate2D( 15 latitude: coordinates.latitude, 16 longitude: coordinates.longitude) 17 } 18 19 func image(forSize size: Int) -> Image { 20 ImageStore.shared.image(name: imageName, size: size) 21 } 22 23 enum Category: String, CaseIterable, Codable, Hashable { 24 case featured = "Featured" 25 case lakes = "Lakes" 26 case rivers = "Rivers" 27 } 28 } 29 30 struct Coordinates: Hashable, Codable { 31 var latitude: Double 32 var longitude: Double 33 }
第4步
切換回並刪除呼叫。LandmarkList.swift
identified(by:)
從如今開始,您將可以Landmark
直接使用元素集合。
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 List(landmarkData) { landmark in 6 LandmarkRow(landmark: landmark) 7 } 8 } 9 } 10 11 struct LandmarkList_Previews: PreviewProvider { 12 static var previews: some View { 13 LandmarkList() 14 } 15 }
列表正確呈現,但您沒法點擊單個地標以查看該地標的詳細信息頁面。
您能夠經過將導航功能嵌入到列表中,而後將每行嵌套在一個列表中來設置轉換到目標視圖,從而將導航功能添加到列表中。NavigationView
NavigationButton
第1步
將動態生成的地標列表嵌入到。NavigationView
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 NavigationView { 6 List(landmarkData) { landmark in 7 LandmarkRow(landmark: landmark) 8 } 9 } 10 } 11 } 12 13 struct LandmarkList_Previews: PreviewProvider { 14 static var previews: some View { 15 LandmarkList() 16 } 17 }
第2步
調用修改器方法以在顯示列表時設置導航欄的標題。navigationBarTitle(_:)
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 NavigationView { 6 List(landmarkData) { landmark in 7 LandmarkRow(landmark: landmark) 8 } 9 .navigationBarTitle(Text("Landmarks")) 10 } 11 } 12 } 13 14 struct LandmarkList_Previews: PreviewProvider { 15 static var previews: some View { 16 LandmarkList() 17 } 18 }
第3步
在列表的閉包內,將返回的行包裝在a中,將視圖指定爲目標。NavigationButton
LandmarkDetail
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 NavigationView { 6 List(landmarkData) { landmark in 7 NavigationButton(destination: LandmarkDetail()) { 8 LandmarkRow(landmark: landmark) 9 } 10 } 11 .navigationBarTitle(Text("Landmarks")) 12 } 13 } 14 } 15 16 struct LandmarkList_Previews: PreviewProvider { 17 static var previews: some View { 18 LandmarkList() 19 } 20 }
第4步
您能夠經過切換到實時模式直接在預覽中嘗試導航。單擊「實時預覽」按鈕,而後點擊地標以訪問詳細信息頁面。
該視圖仍然使用硬編碼的細節,以顯示其標誌性建築。就像它所包含的類型和視圖須要使用屬性做爲其數據的源。LandmarkDetail
LandmarkRow
LandmarkDetail
landmark
從子視圖開始,您將轉換,而後顯示傳入的數據,而不是硬編碼每一行。CircleImage
MapView
LandmarkDetail
第1步
在添加存儲的屬性。CircleImage.swift
image
CircleImage
這是使用SwiftUI構建視圖時的常見模式。您的自定義視圖一般會爲特定視圖包裝和封裝一系列修改器。
1 import SwiftUI 2 3 struct CircleImage: View { 4 var image: Image 5 6 var body: some View { 7 image 8 .clipShape(Circle()) 9 .overlay(Circle().stroke(Color.white, lineWidth: 4)) 10 .shadow(radius: 10) 11 } 12 } 13 14 struct CircleImage_Preview: PreviewProvider { 15 static var previews: some View { 16 CircleImage() 17 } 18 }
第2步
更新預覽提供程序以傳遞Turtle Rock的圖像。
1 import SwiftUI 2 3 struct CircleImage: View { 4 var image: Image 5 6 var body: some View { 7 image 8 .clipShape(Circle()) 9 .overlay(Circle().stroke(Color.white, lineWidth: 4)) 10 .shadow(radius: 10) 11 } 12 } 13 14 struct CircleImage_Preview: PreviewProvider { 15 static var previews: some View { 16 CircleImage(image: Image("turtlerock")) 17 } 18 }
第3步
在,添加屬性並轉換代碼以使用該屬性而不是硬編碼緯度和經度。MapView.swift
coordinate
MapView
1 import SwiftUI 2 import MapKit 3 4 struct MapView: UIViewRepresentable { 5 var coordinate: CLLocationCoordinate2D 6 7 func makeUIView(context: Context) -> MKMapView { 8 MKMapView(frame: .zero) 9 } 10 11 func updateUIView(_ view: MKMapView, context: Context) { 12 13 let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02) 14 let region = MKCoordinateRegion(center: coordinate, span: span) 15 view.setRegion(region, animated: true) 16 } 17 } 18 19 struct MapView_Preview: PreviewProvider { 20 static var previews: some View { 21 MapView() 22 } 23 }
第4步
更新預覽提供程序以傳遞數據數組中第一個地標的座標。
1 import SwiftUI 2 import MapKit 3 4 struct MapView: UIViewRepresentable { 5 var coordinate: CLLocationCoordinate2D 6 7 func makeUIView(context: Context) -> MKMapView { 8 MKMapView(frame: .zero) 9 } 10 11 func updateUIView(_ view: MKMapView, context: Context) { 12 let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02) 13 let region = MKCoordinateRegion(center: coordinate, span: span) 14 view.setRegion(region, animated: true) 15 } 16 } 17 18 struct MapView_Preview: PreviewProvider { 19 static var previews: some View { 20 MapView(coordinate: landmarkData[0].locationCoordinate) 21 } 22 }
第5步
在,向該類型添加屬性。LandmarkDetail.swift
Landmark
LandmarkDetail
1 import SwiftUI 2 3 struct LandmarkDetail: View { 4 var landmark: Landmark 5 6 var body: some View { 7 VStack { 8 MapView() 9 .frame(height: 300) 10 11 CircleImage() 12 .offset(y: -130) 13 .padding(.bottom, -130) 14 15 VStack(alignment: .leading) { 16 Text("Turtle Rock") 17 .font(.title) 18 19 HStack(alignment: .top) { 20 Text("Joshua Tree National Park") 21 .font(.subheadline) 22 Spacer() 23 Text("California") 24 .font(.subheadline) 25 } 26 } 27 .padding() 28 29 Spacer() 30 } 31 } 32 } 33 34 struct LandmarkDetail_Preview: PreviewProvider { 35 static var previews: some View { 36 LandmarkDetail() 37 } 38 }
第6步
更新預覽以使用第一個地標。landmarkData
1 import SwiftUI 2 3 struct LandmarkDetail: View { 4 var landmark: Landmark 5 6 var body: some View { 7 VStack { 8 MapView() 9 .frame(height: 300) 10 11 CircleImage() 12 .offset(y: -130) 13 .padding(.bottom, -130) 14 15 VStack(alignment: .leading) { 16 Text("Turtle Rock") 17 .font(.title) 18 19 HStack(alignment: .top) { 20 Text("Joshua Tree National Park") 21 .font(.subheadline) 22 Spacer() 23 Text("California") 24 .font(.subheadline) 25 } 26 } 27 .padding() 28 29 Spacer() 30 } 31 } 32 } 33 34 struct LandmarkDetail_Preview: PreviewProvider { 35 static var previews: some View { 36 LandmarkDetail(landmark: landmarkData[0]) 37 } 38 }
第7步
將所需數據傳遞給您的自定義類型。
1 import SwiftUI 2 3 struct LandmarkDetail: View { 4 var landmark: Landmark 5 6 var body: some View { 7 VStack { 8 MapView(coordinate: landmark.locationCoordinate) 9 .frame(height: 300) 10 11 CircleImage(image: landmark.image(forSize: 250)) 12 .offset(y: -130) 13 .padding(.bottom, -130) 14 15 VStack(alignment: .leading) { 16 Text(landmark.name) 17 .font(.title) 18 19 HStack(alignment: .top) { 20 Text(landmark.park) 21 .font(.subheadline) 22 Spacer() 23 Text(landmark.state) 24 .font(.subheadline) 25 } 26 } 27 .padding() 28 29 Spacer() 30 } 31 } 32 } 33 34 struct LandmarkDetail_Preview: PreviewProvider { 35 static var previews: some View { 36 LandmarkDetail(landmark: landmarkData[0]) 37 } 38 }
第8步
最後,在顯示詳細視圖時,調用修改器爲導航欄指定標題。navigationBarTitle(_:displayMode:)
1 import SwiftUI 2 3 struct LandmarkDetail: View { 4 var landmark: Landmark 5 6 var body: some View { 7 VStack { 8 MapView(coordinate: landmark.locationCoordinate) 9 .frame(height: 300) 10 11 CircleImage(image: landmark.image(forSize: 250)) 12 .offset(y: -130) 13 .padding(.bottom, -130) 14 15 VStack(alignment: .leading) { 16 Text(landmark.name) 17 .font(.title) 18 19 HStack(alignment: .top) { 20 Text(landmark.park) 21 .font(.subheadline) 22 Spacer() 23 Text(landmark.state) 24 .font(.subheadline) 25 } 26 } 27 .padding() 28 29 Spacer() 30 } 31 .navigationBarTitle(Text(landmark.name), displayMode: .inline) 32 } 33 } 34 35 struct LandmarkDetail_Preview: PreviewProvider { 36 static var previews: some View { 37 LandmarkDetail(landmark: landmarkData[0]) 38 } 39 }
第9步
在,切換應用程序的根視圖。SceneDelegate.swift
LandmarkList
您的應用程序以在模擬器中獨立運行時定義的根視圖而不是預覽開始。SceneDelegate
1 import UIKit 2 import SwiftUI 3 4 class SceneDelegate: UIResponder, UIWindowSceneDelegate { 5 var window: UIWindow? 6 7 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 8 // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 9 // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 10 // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 11 12 // Use a UIHostingController as window root view controller 13 let window = UIWindow(frame: UIScreen.main.bounds) 14 window.rootViewController = UIHostingController(rootView: LandmarkList()) 15 self.window = window 16 window.makeKeyAndVisible() 17 } 18 19 // ... 20 }
第10步
在,將當前地標傳遞到目的地。LandmarkList.swift
LandmarkDetail
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 NavigationView { 6 List(landmarkData) { landmark in 7 NavigationButton(destination: LandmarkDetail(landmark: landmark)) { 8 LandmarkRow(landmark: landmark) 9 } 10 } 11 .navigationBarTitle(Text("Landmarks")) 12 } 13 } 14 } 15 16 struct LandmarkList_Previews: PreviewProvider { 17 static var previews: some View { 18 LandmarkList() 19 } 20 }
第11步
從列表導航時,切換到實時預覽以查看詳細視圖顯示正確的標記。
接下來,您將向預覽提供程序添加代碼,以便以不一樣的設備大小呈現列表視圖的預覽。默認狀況下,預覽會以活動方案中設備的大小進行渲染。您能夠經過調用修改器方法來更改預覽設備。LandmarkList_Previews
previewDevice(_:)
第1步
首先,將當前列表預覽更改成以iPhone SE的大小呈現。
您能夠提供Xcode方案菜單中顯示的任何設備的名稱。
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 NavigationView { 6 List(landmarkData) { landmark in 7 NavigationButton(destination: LandmarkDetail(landmark: landmark)) { 8 LandmarkRow(landmark: landmark) 9 } 10 } 11 .navigationBarTitle(Text("Landmarks")) 12 } 13 } 14 } 15 16 struct LandmarkList_Previews: PreviewProvider { 17 static var previews: some View { 18 LandmarkList() 19 .previewDevice(PreviewDevice(rawValue: "iPhone XS")) 20 } 21 }
第2步
在列表預覽中,使用設備名稱數組做爲數據嵌入實例中。LandmarkList
ForEach
ForEach
以與列表相同的方式對集合進行操做,這意味着您能夠在任何可使用子視圖的位置使用它,例如在堆棧,列表,組等中。當數據元素是簡單的值類型(如您在此處使用的字符串)時,您能夠將其\.self
用做標識符的關鍵路徑。
第3步
使用修改器將設備名稱添加爲預覽的標籤。previewDisplayName(_:)
1 import SwiftUI 2 3 struct LandmarkList: View { 4 var body: some View { 5 NavigationView { 6 List(landmarkData) { landmark in 7 NavigationButton(destination: LandmarkDetail(landmark: landmark)) { 8 LandmarkRow(landmark: landmark) 9 } 10 } 11 .navigationBarTitle(Text("Landmarks")) 12 } 13 } 14 } 15 16 struct LandmarkList_Previews: PreviewProvider { 17 static var previews: some View { 18 ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in 19 LandmarkList() 20 .previewDevice(PreviewDevice(rawValue: deviceName)) 21 .previewDisplayName(deviceName) 22 } 23 } 24 }
第4步
您能夠嘗試使用不一樣的設備來比較視圖的渲染,全部這些都來自畫布。