SwiftUI 数据表单Form的四个层次思考模式

  • 初学层次

简单使用HStack + Image + TextField等控件组合,快速实现需求

import SwiftUI

struct SignUpForm0: View {
    @State var username = ""
    @State var pwd = ""
    
    var body: some View {
        NavigationView{
            Form {
                Text("注册界面").font(.headline)
                HStack {
                    Image(systemName: "person.circle.fill")
                    TextField("Username", text: $username)
                }
                HStack {
                    Image(systemName: "envelope.circle.fill")
                    TextField("pwd", text: $pwd)
                }
                Button(
                    action: { print("here") },
                    label: { Text("提交") }
                )
            }.navigationBarTitle(Text("用户注册界面"))
        }
    }
}
  • 入门层次

代码复用,在构建界面时开始使用模块化思想,封装成一个独立的组件,通过数据流绑定Bingding来进行数值的传递。

struct IconPrefixedTextField: View {
    var iconName: String
    var title: String
    @Binding var text: String
    
    var body: some View {
        HStack {
            Image(systemName: iconName)
            TextField(title, text: $text)
        }
    }
}

import SwiftUI

struct SignUpForm1: View {
    @State var username = ""
    @State var pwd = ""
    
    var body: some View {
        NavigationView{
            Form {
                Text("注册界面").font(.headline)
                IconPrefixedTextField(
                    iconName: "person.circle.fill",
                    title: "Username",
                    text: $username
                )
                IconPrefixedTextField(
                    iconName: "envelope.circle.fill",
                    title: "pwd",
                    text: $pwd
                )
                Button(
                    action: { print("here") },
                    label: { Text("提交") }
                )
            }.navigationBarTitle(Text("用户注册界面"))
        }
    }
}
  • 进阶层次

根据SwiftUI框架的API设计原则,对View进行灵活扩展

extension View {
    func prefixedWithIcon(named name: String) -> some View {
        HStack {
            Image(systemName: name)
            self
        }
    }
}


import SwiftUI

struct SignUpForm2: View {
    @State var username = ""
    @State var pwd = ""
    
    var body: some View {
        NavigationView{
            Form {
                Text("注册界面").font(.headline)
                
                TextField("Username", text: $username)
                    .prefixedWithIcon(named: "person.circle.fill")
                TextField("pwd", text: $pwd)
                    .prefixedWithIcon(named: "envelope.circle.fill")
                
                Button(
                    action: { print("here") },
                    label: { Text("提交") }
                )
            }.navigationBarTitle(Text("用户注册界面"))
        }
    }
}
  • 中高级层次

由界面的改造开始将注意力集中在业务逻辑方面抽离处理。

用户注册账号、密码的验证、及界面刷新

  1. RegexValidate 正则工具类,校验账号密码

  2. 创建 ViewModifier 当用户满足条件就刷新UI

struct Validation<Value>: ViewModifier {
    var value: Value
    var validator: (Value) -> Bool
    
    func body(content: Content) -> some View {
        // 使用Group擦除类型
        Group {
            if validator(value) {
                content.border(Color.green)
            } else {
                content
            }
        }
    }
}
  1. 主界面
struct SignUpForm3: View {
    @State var username = ""
    @State var pwd = ""
    @State var uFlag = false
    @State var pFlag = false
    
    
    var body: some View {
        NavigationView{
            Form {
                Text("注册界面").font(.headline)
                TextField("Username", text: $username)
                    .modifier(Validation(value: username) { name in
                        self.uFlag = name.count > 4
                        return self.uFlag
                        
                    })
                    .prefixedWithIcon(named: "person.circle.fill")
                
                TextField("pwd", text: $pwd)
                    .modifier(Validation(value: pwd) { name in
                       self.pFlag = RegexValidate.password(name).isRight
                        return self.pFlag
                        
                    })
                    .prefixedWithIcon(named: "envelope.circle.fill")
                
                if (self.uFlag && self.pFlag){
                Button(
                    action: {print("here")},
                    label: { Text("提交") }
                )
                }
            }.navigationBarTitle(Text("用户注册界面"))
        }
    }
}

posted on 2020-04-10 22:46  码上翻身  阅读(567)  评论(0编辑  收藏  举报

导航