SwiftUI 官方教程(七)
7. 给子 View 传递数据
LandmarkDetail 现在依然使用硬编码的数据来显示地标。像 LandmarkRow 一样,LandmarkDetail 类型和它组合的其他 view 都需要一个 landmark 属性作为它们的数据源。
在开始子 view 的内容时,我们会把 CircleImage 、 MapView 和 LandmarkDetail 的显示从硬编码改为传入的数据。SwiftUI 官方教程

7.1 在 CircleImage.swif 中,添加存储属性 image 。SwiftUI教程
这是使用 SwiftUI 构建 view 时的常见模式。我们的自定义 view 通常会为特定视图包装和封装一些 modifiers 。
CircleImage.swift
import SwiftUI
struct CircleImage: View {
var image: Image
var body: some View {
image
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
}
}
struct CircleImage_Preview: PreviewProvider {
static var previews: some View {
CircleImage()
}
}
7.2 更新 preview provider ,传递一个 Turtle Rock 的图片。
CircleImage.swift
import SwiftUI
struct CircleImage: View {
var image: Image
var body: some View {
image
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
}
}
struct CircleImage_Preview: PreviewProvider {
static var previews: some View {
CircleImage(image: Image("turtlerock"))
}
}
7.3 在 MapView.swift 中,给 MapView 添加一个 coordinate 属性,然后把经纬度的硬编码换成使用这个属性。SwiftUI教程
MapView.swift
import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
struct MapView_Preview: PreviewProvider {
static var previews: some View {
MapView()
}
}
7.4 更新 preview provider ,传递数据数组中第一个地标的坐标。
MapView.swift
import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
struct MapView_Preview: PreviewProvider {
static var previews: some View {
MapView(coordinate: landmarkData[0].locationCoordinate)
}
}
7.5 在 LandmarkDetail.swift 中,SwiftUI教程 给 LandmarkDetail 类型添加 landmark 属性。
LandmarkDetail.swift
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
VStack {
MapView()
.frame(height: 300)
CircleImage()
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack(alignment: .top) {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
.padding()
Spacer()
}
}
}
struct LandmarkDetail_Preview: PreviewProvider {
static var previews: some View {
LandmarkDetail()
}
}
7.6 更新 preview provider ,使用 landmarkData 中的第一个地标。
LandmarkDetail.swift
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
VStack {
MapView()
.frame(height: 300)
CircleImage()
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack(alignment: .top) {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
.font(.subheadline)
}
}
.padding()
Spacer()
}
}
}
struct LandmarkDetail_Preview: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
}
}
7.7 将所需数据传递给我们的自定义类型。
LandmarkDetail.swift
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
VStack {
MapView(coordinate: landmark.locationCoordinate)
.frame(height: 300)
CircleImage(image: landmark.image(forSize: 250))
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
Text(landmark.name)
.font(.title)
HStack(alignment: .top) {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
}
.padding()
Spacer()
}
}
}
struct LandmarkDetail_Preview: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
}
}
7.8 最后,调用 navigationBarTitle(_:displayMode:) 方法,给导航栏添加显示详情 view 时的标题。
LandmarkDetail.swift
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
VStack {
MapView(coordinate: landmark.locationCoordinate)
.frame(height: 300)
CircleImage(image: landmark.image(forSize: 250))
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
Text(landmark.name)
.font(.title)
HStack(alignment: .top) {
Text(landmark.park)
.font(.subheadline)
Spacer()
Text(landmark.state)
.font(.subheadline)
}
}
.padding()
Spacer()
}
.navigationBarTitle(Text(landmark.name), displayMode: .inline)
}
}
struct LandmarkDetail_Preview: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
}
}
7.9 在 SceneDelegate.swift 中,把 app 的 rootView 改成 LandmarkList 。
当我们不使用预览而是在模拟器中独立运行 app 时,app 会以 SceneDelegate 中定义的 rootView开始显示。
SceneDelegate.swift
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Use a UIHostingController as window root view controller
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(rootView: LandmarkList())
self.window = window
window.makeKeyAndVisible()
}
// ...
}

7.10 在 LandmarkList.swift 中,给目标 LandmarkDetail 传递当前的地标。
LandmarkList.swift
import SwiftUI
struct LandmarkList: View {
var body: some View {
NavigationView {
List(landmarkData) { landmark in
NavigationButton(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
.navigationBarTitle(Text("Landmarks"))
}
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
}
}

7.11 切换到实时预览,可以查看从列表导航到正确的地标详情 view 了。

SwiftUI 官方教程(七)的更多相关文章
- SwiftUI 官方教程(八)
8. 动态生成预览 接下来,我们会在 LandmarkList_Previews 中添加代码以在不同的设备尺寸上渲染列表.默认情况下,预览会以当前的 scheme 中设备的大小进行渲染.我们可以通过调 ...
- SwiftUI 官方教程(五)
SwiftUI官方教程(五) 5. 同时使用 UIKit 和 SwiftUI 至此,我们已准备好创建 map view 了,接下来使用 MapKit 中的 MKMapView 类来渲染地图. 在 Sw ...
- SwiftUI 官方教程(四)
SwiftUI 官方教程(四) 4. 自定义 Image View 搞定名称和位置 view 后,我们来给地标添加图片. 这不需要添加很多代码,只需要创建一个自定义 view,然后给图片加上遮罩.边框 ...
- SwiftUI 官方教程(三)
3. 用 Stacks 组合 View 在上一节创建标题 view 后,我们来添加 text view,它用来显示地标的详细信息,比如公园的名称和所在的州. 在创建 SwiftUI view 时,我们 ...
- SwiftUI 官方教程(二)
SwiftUI 官方教程(二) 2. 自定义 Text View 为了自定义 view 的显示,我们可以自己更改代码,或者使用 inspector 来帮助我们编写代码. 在构建 Landmarks 的 ...
- SwiftUI 官方教程(一)
完整中文教程及代码请查看 https://github.com/WillieWangWei/SwiftUI-Tutorials 创建和组合 View 此部分将指引你构建一个发现和分享您喜爱地方的 ...
- SwiftUI 官方教程
SwiftUI 官方教程 完整中文教程及代码请查看 https://github.com/WillieWangWei/SwiftUI-Tutorials SwiftUI 官方教程 SwiftUI ...
- SwiftUI 官方教程(六)
6. 在列表和详情之间设置导航 虽然列表已经能显示了,但是我们还不能通过点击单个地标来查看地标详情页面.SwiftUI教程 把 list 嵌入一个 NavigationView 中,并把每个 row ...
- DroidParts 中文系列教程(基于官方教程)
DroidParts中文系列教程(基于官方教程) (一)DroidParts框架概况 2014年4月18日星期五 11:36 他是一个精心构造的安卓框架,包括下面这些基本功能 DI依赖注入,可以注入V ...
随机推荐
- Microsoft Azure Storage Explorer
上周主管说,要把每次开过的发票,要下载成Pdf的文件,然后就实时的将这些发票存到云上面去. 就是这个Microsoft Azure ,微软的亲儿子. 先把代码贴上来吧,挺简单的. ##.链接账号密码 ...
- 设计包含min()函数的栈
题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素.要求函数min.push以及pop的时间复杂度都是O(1). 分析:这是去年google的一道面试题. 我看到这道题目时,第一反应 ...
- DNN:逻辑回归与 SoftMax 回归方法
UFLDL Tutorial 翻译系列:http://deeplearning.stanford.edu/wiki/index.php/UFLDL_Tutorial 第四章:SoftMax回归 简介: ...
- Swift - AnyClass,元类型和 .self
在Swift中能够表示 “任意” 这个概念的除了 Any 和 AnyObject 以外,还有一个AnyClass.我们能够使用AnyClass协议作为任意类型实例的具体类型.AnyClass在Swif ...
- C++ (带有默认参数的函数参数)缺省函数参数
缺省参数?在C++中,允许实参的个数与形参的个数不同.在声明函数原型时,为一个或者多个形参指定默认值,以后调用这个函数时,若省略某一个实参,c++则自动的以默认值作为相应参数的值. 实列说明:#inc ...
- Scala语言学习笔记——方法、函数及异常
1.Scala 方法及函数区别 ① Scala 有方法与函数,二者在语义上的区别很小.Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量.换句话来说在类中定义的函数即是方法 ② Scal ...
- java中为什么不允许类多重继承,却允许接口多重继承
首先看下面这一段代码:(底下有热心网友更正,jdk1.8之后情况确实有点变化,等改天有空继续更) interface a{ void b();}interface a1 extends a{ void ...
- 【转载】java文件路径问题及getResource和getClassLoader().getResource的区别
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u012572955/article/details/52880520我们经常在java的io操作中读 ...
- Linux下进程与线程的区别
https://www.cnblogs.com/fah936861121/articles/8043187.html https://my.oschina.net/cnyinlinux/blog/36 ...
- php实现网站访客数量统计的方法(简单实现,不能防刷新)
方法一: <?php function Counter()//定义函数 { $five = "00000";//声明变量,$five,$four等变量表示零的个数,放在数字前 ...