iOS 成长之路Mac·iOS开发IT/互联网

干货:教你快速使用 SwiftUI 开发 App

2020-06-06  本文已影响0人  腾飞tengfei
SwiftUI

SwiftUI 是一种非常简单的创新方法,可以利用 Swift 的强大能力在所有苹果设备平台上构建用户界面。通过 SwiftUI,开发者仅使用一组工具和 API 就能为所有苹果设备构建用户界面。SwiftUI 使用易于阅读和编写的声明式 Swift 语法,可与新的 Xcode 设计工具无缝协作,使你的代码和设计完美同步。SwiftUI 自动支持动态类型、深色模式、本地化和可访问性,你的 SwiftUI 代码将成为你写过的最强大的 UI 代码。

目标

实现一个列表,点击列表的 item,跳转到对应的详情页。

根据苹果官方教程,整理了 SwiftUI Sample

SwiftUI Sample Preview

首先回想一下在 UIKit 中如何实现:

在 SwiftUI 中怎么实现呢?

在实现之前,先看一下所需要的组件,按照用途大致分为基础组件、布局组件和功能性组件,以及 XCode11 提供的新功能。

所需组件

基础组件
布局组件
功能型组件

NavigationView 展示导航栏类似于 UINavigationBar
NavigationLink 类似于 pushViewController: 方法

XCode11相关功能

预览

实时看到对页面的做出的修改

点击预览串口的 Resume 按钮。

如果没有显示预览窗口,则按下图操作打开。

点击可以切换时时预览和静态预览。

拖放

command 键 + 鼠标点击组件,可以方便的添加组件,设置组件属性等。

代码实现

创建列表
struct LandmarkList : View {
    var body: some View {
        // 自定义显示的内容
        List(0 ..< 5) { item in
            Text("hello")
                .font(.title)
        }
    }
}

使用 List 组件可以快速的创建滑动列表,不需要设置代理,不需要实现协议方法就达到类似于 UIKit 中 UITableView 的效果。

Text 用来展示文字,通过 .font 设置了字体大小。将它放入 List 中,它就是列表的 Item。

从工程 Resources 文件夹中找到资源文件,引入工程,里面包含了 json 数据、图片等。再引入 Models 文件夹中的 Data.swiftLandmark.swift,这些主要是为了组件数据和 Model,不是本文讨论的重点,下面会用到这些数据。

创建 Item

这一步在 UIKit 中像自定义 UITableViewCell,需要再其中添加一个图片和一个文字。

在 SwiftUI 中,没有 UITableViewCell 的概念,需要显示一行的时候,只需要使用 HStack 组件,HStack 组件是一个组合组件,其中可以放 TextImage 等组件。

创建 LandmarkRow

struct LandmarkRow : View {
    var landmark: Landmark
    
    var body: some View {
        HStack {
            landmark.image(forSize: 50)
            Text(landmark.name)
        }
    }
}

landmark.image(forSize: 50) 这个方法返回一个指定大小的图片

Text 显示地标名称。

HStack 将图片和文字组合在一行里面显示,并配置的有默认格式。

效果:

把它带入第一步创建的列表中,并引入数据。

struct LandmarkList : View {
    var body: some View {        
        List(landmarkData) { landmark in
            LandmarkRow(landmark: landmark)
        }   
    }
}

效果:

列表已经显示出来了。

想想 UIKit 中的那堆代码,是不是暗爽?

创建详情页

从效果图中看到详情页有一个地图、一个圆形图片、几个显示地名、位置的文字。

从布局上看最下面两个水平的文字可以摆放在水平组件中,再和标题文字一起摆放在竖直组件中。

地图、图片、水平摆放的组件再一起摆放在竖直摆放组件中。

创建地图模块:

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)
    }
}

要在 SwiftUI 中添加非 SwiftUI 的组件,需要遵循 UIViewRepresentable 协议,并实现协议方法。

创建圆角图片:

struct CircleImage : View {
    
    var image: Image
    
    var body: some View {
        image
        .clipShape(Circle())
        .overlay(
            Circle().stroke(Color.white, lineWidth: 4)
            .shadow(radius: 10)
        )
    }
}

创建详情页

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 {
                    Text(landmark.park)
                        .font(.subheadline)
                    Spacer()
                    Text(landmark.state)
                        .font(.subheadline)
                }
                }
                .padding()
            Spacer()
        }
    }
}

VStack 竖直组合组件,里面包含了 MapViewCircleImage 以及 VStack

VStack 中包含了标题文字以及HStack

HStack 中包含了水平摆放的两个文字组件。

效果:

实现跳转

上面已经分别实现了列表页和详情页面,下面实现跳转。

UIKit 中想要 Push 效果需要创建 UINavigationController ,想要显示导航栏需要设置 UINavigationBar,想要跳转需要在 UITableView 的代理方法中调用 pushViewController: 方法。

修改上面创建的列表:

struct LandmarkList : View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                    LandmarkRow(landmark: landmark)
                 }
                }
                .navigationBarTitle(Text("Landmarks"), displayMode: .inline)
        }
    }
}

NavigationView 组件类似于 UINavigationBar,可以设置导航栏标题和模式。

NavigationLink 可以直接将跳转方法直接和列表展示绑定在一起,逻辑更清晰明了。

总结

了解过 Flutter 的同学对这个接受可能会很快。

没有了解过 Flutter 的同学需要转变一下页面布局思路。

SwiftUI 对 iOS 开发同学来是一大福音,毕竟都2019年了,还在使用 UIKit 中这么原始的布局,实在是苦不堪言。

SwiftUI 需要 iOS13 以上的系统,但目前公司开发 App 都会支持一定的老版本系统,还得使用 UIKit。全面使用 SwiftUI 预计还有一段时间。毕竟,还有很多公司没有使用 Swift 呢。

写的有不好的地方希望大家指出,我会更正,大家有什么看不明白的,也可以在评论里面提问,我会尽力解答。另附 Apple 官方 SwiftUI Tutorials


点赞+关注,第一时间获取技术干货和最新知识点,谢谢你的支持!转发请注明出处

最后祝大家生活愉快~

上一篇下一篇

猜你喜欢

热点阅读