★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(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( 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( 300, height: 70)) 19 LandmarkRow(landmark: landmarkData[1]) 20 .previewLayout(.fixed( 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( 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步
您可以尝试使用不同的设备来比较视图的渲染,所有这些都来自画布。