★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公眾號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/11075270.html
➤如果鏈接不是山青詠芝的博客園地址,則可能是爬取作者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持作者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
設置基本地標詳細信息視圖后,您需要為用戶提供查看完整地標列表以及查看每個位置詳細信息的方法。
您將創建可顯示有關任何地標的信息的視圖,並動態生成滾動列表,用戶可以點按該列表以查看地標的詳細視圖。要微調UI,您將使用Xcode的畫布以不同的設備大小呈現多個預覽。
下載項目文件以開始構建此項目,並按照以下步驟操作。
一、了解樣本數據
在[SwiftUI教程]2、創建和組合視圖中,您將信息硬編碼到所有自定義視圖中。在這里,您將學習將數據傳遞到自定義視圖中以供顯示。
首先下載入門項目並熟悉示例數據。
第1步
在Project導航器中,選擇Models > Landmark.swift
.
Landmark.swift
聲明一種Landmark
結構,存儲應用程序需要顯示的所有地標信息,並從中導入一系列地標數據。landmarkData.json
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步
您可以嘗試使用不同的設備來比較視圖的渲染,所有這些都來自畫布。