教你快速使用 SwiftUI 开发 App

SwiftUI

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

目标

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

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

SwiftUI Sample Preview

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

  • 创建一个带导航 Navigation 的 controller,用来布局和 Push 下一个页面。
  • 添加 UITableView,并实现 UITableView 的两个代理方法,展示列表。
  • 创建 UITableViewCell,布局 UILabel 和 UIImageView。
    创建详情页面,布局地图、三个 UIlabel。
  • 在 UITableViewDelegate 的代理方法中 Push 到详情页。
  • 对 iOS 开发来说这太简单太熟悉不过了,但很多代码比较繁琐,控件的创建、布局等。虽然简单,但繁琐,浪费了很多本该花在业务上的时间。

在 SwiftUI 中怎么实现呢?

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

所需组件

基础组件
  • Text 用来显示文字 类似于 UIKit 中的 UILabel
  • Image 用来显示图片 类似于 UIKit 中的 UIImageView
  • Spacer 用来填充空白
布局组件
  • VStack 竖直摆放的组合组件
  • HStack水平摆放的组合组件
  • List 用来展示列表 类似于 UIKit 中的 UITableView
功能型组件

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

XCode11相关功能

预览

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

  • 纯 SwiftUI 时,默认静态预览。

点击预览串口的 Resume 按钮。

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

  • 预览包含 UIView 子类视图时,需要打开时时预览

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

拖放

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。


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

最后祝大家生活愉快~

你可能感兴趣的:(教你快速使用 SwiftUI 开发 App)