zoukankan      html  css  js  c++  java
  • 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 了。

  • 相关阅读:
    MeasureSpec学习
    android之GridView实现九宫格布局
    android 检查网络是否可用,如果不可用弹出设置,让用户改变
    Android Studio中新建项目时Your android sdk is out of date or is missing templates的解决办法
    android studio 改变主题及字体大小
    使用URL读取网络图片资源
    Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V
    android获取在res文件下的图片资源
    星座物语APP
    第十三次会议
  • 原文地址:https://www.cnblogs.com/suibian1/p/11030907.html
Copyright © 2011-2022 走看看