Проверка электронной почты SwiftUI - PullRequest
2 голосов
/ 30 января 2020

Как выполняется проверка электронной почты с помощью swiftUI?

TextField("Please enter your e-mail", text: self.$email)
    .modifier(ClearButton(text: $email))
    .font(.headline)
    .padding(10)
    .foregroundColor(.black)
    .background(Color.white)
    .frame(width: 300, height: 40, alignment: .center)
    .cornerRadius(20)

Ответы [ 2 ]

3 голосов
/ 30 января 2020

Вам нужно использовать объединение с SwiftUI для проверки

Используйте TextFieldWithValidator для проверки textField

import SwiftUI
import Combine


// MARK:  FIELD VALIDATION

@available(iOS 13, *)
public struct FieldChecker {

    public var errorMessage:String?

    public var valid:Bool {
         self.errorMessage == nil
     }
    public init( errorMessage:String? = nil ) {
        self.errorMessage = errorMessage
    }
}

@available(iOS 13, *)
public class FieldValidator<T> : ObservableObject where T : Hashable {
    public typealias Validator = (T) -> String?

    @Binding private var bindValue:T
    @Binding private var checker:FieldChecker

    @Published public var value:T
    {
        willSet {
            self.doValidate(newValue)
        }
        didSet {
            self.bindValue = self.value
        }
    }
    private let validator:Validator

    public var isValid:Bool {
        self.checker.valid
    }

    public var errorMessage:String? {
        self.checker.errorMessage
    }

    public init( _ value:Binding<T>, checker:Binding<FieldChecker>, validator:@escaping Validator  ) {
        self.validator = validator
        self._bindValue = value
        self.value = value.wrappedValue
        self._checker = checker
    }

    public func doValidate( _ newValue:T? = nil ) -> Void {

        self.checker.errorMessage =
                        (newValue != nil) ?
                            self.validator( newValue! ) :
                            self.validator( self.value )
    }
}


// MARK:  FORM FIELD

@available(iOS 13, *)
public struct TextFieldWithValidator : View {
    // specialize validator for TestField ( T = String )
    public typealias Validator = (String) -> String?

    var title:String?
    var onCommit:() -> Void

    @ObservedObject var field:FieldValidator<String>

    public init( title:String = "",
              value:Binding<String>,
              checker:Binding<FieldChecker>,
              onCommit: @escaping () -> Void,
              validator:@escaping Validator ) {
        self.title = title;
        self.field = FieldValidator(value, checker:checker, validator:validator )
        self.onCommit = onCommit
    }

    public init( title:String = "", value:Binding<String>, checker:Binding<FieldChecker>, validator:@escaping Validator ) {
        self.init( title:title, value:value, checker:checker, onCommit:{}, validator:validator)
    }

    public var body: some View {
        VStack {
            TextField( title ?? "", text: $field.value, onCommit: self.onCommit )
                .onAppear { // run validation on appear
                    self.field.doValidate()
                }
        }
    }
}

@available(iOS 13, *)
public struct SecureFieldWithValidator : View {
    // specialize validator for TestField ( T = String )
    public typealias Validator = (String) -> String?

    var title:String?
    var onCommit:() -> Void

    @ObservedObject var field:FieldValidator<String>

    public init( title:String = "",
              value:Binding<String>,
              checker:Binding<FieldChecker>,
              onCommit: @escaping () -> Void,
              validator:@escaping Validator ) {
        self.title = title;
        self.field = FieldValidator(value, checker:checker, validator:validator )
        self.onCommit = onCommit
    }

    public init( title:String = "", value:Binding<String>, checker:Binding<FieldChecker>, validator:@escaping Validator ) {
        self.init( title:title, value:value, checker:checker, onCommit:{}, validator:validator)
    }

    public var body: some View {
        VStack {
            SecureField( title ?? "", text: $field.value, onCommit: self.onCommit )
                .onAppear { // run validation on appear
                    self.field.doValidate()
                }
        }
    }
}

в вашем представлении

import SwiftUI
import Combine



class DataItem: ObservableObject { // observable object

    @Published var username:String = "" // observable property
}


struct FormWithValidator : View {

    @EnvironmentObject var item:DataItem // data model reference

    @State var usernameValid = FieldChecker() // validation state of username field

    func username() -> some View {
        VStack {
            TextFieldWithValidator( title: "username",
                                value: $item.username,
                                checker: $usernameValid,
                                onCommit: submit) { v in
                         // validation closure where ‘v’ is the current value

                            if( v.isEmpty ) {
                                return "username cannot be empty"
                            }

                            return nil
                    }
                    .padding(.all)
                    .border( usernameValid.valid ? Color.clear : Color.red )
                    .background(Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0))
                    .autocapitalization(.none)
            if( !usernameValid.valid  ) {
                Text( usernameValid.errorMessage ?? "" )
                    .fontWeight(.light)
                    .font(.footnote)
                    .foregroundColor(Color.red)
            }

        }

    }

    var isValid:Bool {
         usernameValid.valid
    }

    func submit() {
        if( isValid ) {
            print( "submit:\nusername:\(self.item.username)")
        }
    }

    var body: some View {

        NavigationView {
        Form {

            Section {
                username()

            }

            Section {

                Button( "Submit" ) {

                    self.submit()
                }
                    .disabled( !self.isValid )
            } // end of section

        } // end of form
           .navigationBarTitle( Text( "Sample Form" ), displayMode: .inline  )

        } // NavigationView
    }
}

#if DEBUG
struct FormVithValidator_Previews: PreviewProvider {
    static var previews: some View {
        FormWithValidator()
            .environmentObject( DataItem() )
    }
}
#endif

enter image description here

Кредиты и вдохновение

2 голосов
/ 30 апреля 2020

Проверка может быть выполнена просто с использованием onEditingChanged любого TextField.

Ниже приведен код для проверки электронной почты, но его можно использовать для любой другой проверки.

Когда пользователь закончил и существует текстовое поле, я проверяю текст, а если он не проверяется, я удаляю текст с ошибкой под ним.

import SwiftUI
struct ContentView: View {

@State private var emailString  : String = ""
@State private var textEmail    : String = ""
@State private var isEmailValid : Bool   = true

var body: some View {
    VStack {
        TextField("email...", text: $textEmail, onEditingChanged: { (isChanged) in
            if !isChanged {
                if self.textFieldValidatorEmail(self.textEmail) {
                    self.isEmailValid = true
                } else {
                    self.isEmailValid = false
                    self.textEmail = ""
                }
            }
        })
            //.modifier(ClearButton(text: $email))
            .font(.headline)
            .padding(10)
            .foregroundColor(.black)
            .background(Color.white)
            .frame(width: 300, height: 40, alignment: .center)
            .cornerRadius(20)
            .autocapitalization(.none)

        if !self.isEmailValid {
            Text("Email is Not Valid")
                .font(.callout)
                .foregroundColor(Color.red)
        }
    }
}

func textFieldValidatorEmail(_ string: String) -> Bool {
    if string.count > 100 {
        return false
    }
    let emailFormat = "(?:[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}" + "~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" + "x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\p{L}0-9](?:[a-" + "z0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?|\\[(?:(?:25[0-5" + "]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + "9][0-9]?|[\\p{L}0-9-]*[\\p{L}0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21" + "-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
    //let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluate(with: string)
}}

onEditingChanged: когда пользователь нажимает на это, isChanged = true, а когда пользователь выходит и уходит куда-то еще, isChange = false.

...