今日职言:不要为昨天已发生的事情而懊悔,也不要为明天未发生的事情而畏缩。

在本章中,你将学会如何使用​​Combine​​​异步编程框架和​​MVVM​​​开发模式完成一个​​登录注册​​页面及其逻辑交互。

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_密码输入框

在几乎所有​​App​​中,都需要一个用户注册登录页面,用来获取和绑定用户信息。用户量,特别是付费用户量,决定这一款产品能否成为爆款商品。

因此,做好注册登录页面是非要有必要的。

那么,我们开始吧。

项目创建

首先,创建一个新项目,命名为​​SwiftUIRegistration​​。

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_输入框_02

主要页面绘制

我们简单分析下页面组成,它由一个用户名称输入框、一个密码输入框、一个密码二次确认输入框组成。

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_用户名_03

首先是用户名称输入框,它是一个简答的​​TextField​​​输入框,我们只需要使用​​@State​​​初始化存储一个​​String​​类型的参数,绑定就可以了。

//用户名
TextField("用户名", text: $username)
.font(.system(size: 20, weight: .semibold))
.padding(.horizontal)

然后是密码输入框,它有点不同,在​​SwiftUI​​​中,除了​​TextField​​​输入框外,还有一种密码类型的输入框​​SecureField​​​,使用方法和​​TextField​​输入框类似。

//密码
SecureField("密码", text: $password)
.font(.system(size: 20, weight: .semibold))
.padding(.horizontal)

密码二次确认输入框也是同样是​​SecureField​​​密码输入框,为了隔开内容,输入框都可以使用​​Divider​​分割线分开,这样美观一些。

//分割线
Divider()
.frame(height: 1)
.background(Color(red: 240/255, green: 240/255, blue: 240/255))
.padding(.horizontal)

最后是注册按钮,按照之前的章节,我们放一个简单的按钮。

//注册按钮
Button(action: {

}) {
Text("注册")
.font(.system(.body, design: .rounded))
.foregroundColor(.white)
.bold()
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color(red: 51 / 255, green: 51 / 255, blue: 51 / 255))
.cornerRadius(10)
.padding(.horizontal)
}

我们准备好这些元素后,将他们用​​VStack​​纵向排布在一起。

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_用户名_04

代码优化

我们发现,相同的代码太多了,这不够优雅。

哪怕是做任何项目,我们编程都力求优雅。我们可以把相同的内容抽离出来,除了样式外,我们发现​​TextField​​​输入框和​​SecureField​​密码输入框除了类型不一样,其他都是一样的。

那么我们可以通过一个​​判断​​来抽离主体内容。

//注册视图
struct RegistrationView:View {

var isTextField = false
var fieldName = ""
@Binding var fieldValue: String

var body: some View {

VStack {

//判断是不是输入框
if isTextField {
//输入框
TextField(fieldName, text: $fieldValue)
.font(.system(size: 20, weight: .semibold))
.padding(.horizontal)
} else {
//密码输入框
SecureField(fieldName, text: $fieldValue)
.font(.system(size: 20, weight: .semibold))
.padding(.horizontal)
}

//分割线
Divider()
.frame(height: 1)
.background(Color(red: 240/255, green: 240/255, blue: 240/255))
.padding(.horizontal)
}
}
}

然后,我们只需要在​​ContentView​​​主视图中引用并​​绑定​​就完成了页面设计。

RegistrationView(isTextField: true, fieldName: "用户名", fieldValue: $username)
RegistrationView(isTextField: false, fieldName: "密码", fieldValue: $password)
RegistrationView(isTextField: false, fieldName: "再次输入密码", fieldValue: $passwordConfirm)

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_SwiftUI_05

报错信息绘制

然后,我们来实现了报错信息提醒。

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_Swift_06

同理,我们也把相同元素抽离出来,我们可以看到如果校验不通过,它会展示一个​​Image​​​图标和错误信息​​Text​​文字,逻辑我们先放一边,完成页面。

//错误信息
struct InputErrorView:View {

var iconName = ""
var text = ""

var body: some View {

HStack {
Image(systemName: iconName)
.foregroundColor(Color(red: 251/255, green: 128/255, blue: 128/255))
Text(text)
.font(.system(.body, design: .rounded))
.foregroundColor(Color(red: 251/255, green: 128/255, blue: 128/255))
Spacer()
}.padding(.leading,10)
}
}

然后在​​ContentView​​主视图中引用并绑定,效果如下:

SwiftUI极简教程29:Combine异步编程框架和MVVM开发模式的使用(上)_SwiftUI_07

恭喜你,完成了本章页面的设计编程。

由于这一章的内容有点多,那么我们也将分章节写完,不要着急。

下一章,我们将基于这个注册登录页面学习​​Combine​​异步编程框架的使用。

完整代码

import SwiftUI

struct ContentView: View {

@State private var username = ""
@State private var password = ""
@State private var passwordConfirm = ""

var body: some View {

VStack (alignment: .leading, spacing: 40) {

//用户名
VStack {
RegistrationView(isTextField: true, fieldName: "用户名", fieldValue: $username)
InputErrorView(iconName: "exclamationmark.circle.fill", text: "用户不存在")
}

//密码
VStack{
RegistrationView(isTextField: false, fieldName: "密码", fieldValue: $password)
InputErrorView(iconName: "exclamationmark.circle.fill", text: "密码不正确")
}

//再次输入密码
VStack {
RegistrationView(isTextField: false, fieldName: "再次输入密码", fieldValue: $passwordConfirm)
InputErrorView(iconName: "exclamationmark.circle.fill", text: "两次密码需要相同")
}

//注册按钮
Button(action: {

}) {
Text("注册")
.font(.system(.body, design: .rounded))
.foregroundColor(.white)
.bold()
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color(red: 51 / 255, green: 51 / 255, blue: 51 / 255))
.cornerRadius(10)
.padding(.horizontal)
}
}.padding()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

//注册视图
struct RegistrationView:View {

var isTextField = false
var fieldName = ""
@Binding var fieldValue: String

var body: some View {

VStack {

//判断是不是输入框
if isTextField {

//输入框
TextField(fieldName, text: $fieldValue)
.font(.system(size: 20, weight: .semibold))
.padding(.horizontal)
} else {

//密码输入框
SecureField(fieldName, text: $fieldValue)
.font(.system(size: 20, weight: .semibold))
.padding(.horizontal)
}

//分割线
Divider()
.frame(height: 1)
.background(Color(red: 240/255, green: 240/255, blue: 240/255))
.padding(.horizontal)
}
}
}

//错误判断
struct InputErrorView:View {

var iconName = ""
var text = ""

var body: some View {

HStack {
Image(systemName: iconName)
.foregroundColor(Color(red: 251/255, green: 128/255, blue: 128/255))
Text(text)
.font(.system(.body, design: .rounded))
.foregroundColor(Color(red: 251/255, green: 128/255, blue: 128/255))
Spacer()
}.padding(.leading,10)
}
}

快来动手试试吧!

如果本专栏对你有帮助,不妨点赞、评论、关注~