Day#14 注册与按钮

前言

注册与登入需要的元素差不多,因此简单带过注册的程序码。

登入

前一天在输入栏位的部分,使用了textField

而其中有个重要的观念: 委任模式 Delegate
委任模式的意思是,在设计元件或功能时,会定义数个不等的方法(method),但只会定义出这些方法的名称,而这些方法要做什麽事,则是要交由委任(delegate)的对象来实作。

透过设置delegate,可以指定委托对象。在这边我们将对象指定为自己。不过我也不知道,什麽时候、什麽情境下可能为其他物件,QQ
除了设定delegate外,也要注意该物件有被加上相对应的protocal。在这边是UITextFieldDelegate

LoginViewController

viewDidLoad

loginButton.addTarget(self,
                      action: #selector(loginButtonTapped),
                      for: .touchUpInside)
emailField.delegate = self
passwordField.delegate = self

上面我们在viewDidLoad方法中加上按下按钮後触发的方法、以及刚刚提到的委派对象。
方法loginButtonTapped中,我们将textField清除指标,然後确认栏位都已输入资料,接着进行登入的部分。後端的串接,因为使用firebase auth,因此逻辑都包含在firebase的服务,这边就先不多描述。

// validate text fields
@objc private func loginButtonTapped(){

    // dismiss the keyboard
    emailField.resignFirstResponder()
    passwordField.resignFirstResponder()

    guard let email = emailField.text, let password = passwordField.text,
          !email.isEmpty, !password.isEmpty //, password.count >= 6
    else {
        alertUserLoginError()
        return
    }

    //firebase login
}

func alertUserLoginError(){
    let alert = UIAlertController(title: "Oops",
                                  message: "Please enter valid information",
                                  preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Dismiss",
                                  style: .cancel,
                                  handler: nil))
    present(alert, animated: true)
}

当然,也有例外的处理。

最後,别忘了加上刚刚提到的UITextFieldDelegate
在此需要写上方法textFieldShouldReturn

extension LoginViewController: UITextFieldDelegate{
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if textField == emailField {
            passwordField.becomeFirstResponder()
        }
        else if textField == passwordField {
            loginButtonTapped()
        }

        // true if the text field should implement its default behavior for the return button
        return true
    }
}

RegisterViewController

接下来,注册的流程其实大同小异、只是多了一些栏位。因此不多加描述,直接贴上完整的程序码。

import UIKit

class RegisterViewController: UIViewController {

    private let scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.clipsToBounds = true
        return scrollView
    }()

    private let imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(systemName: "person")
        imageView.tintColor = .lightGray
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    private let firstNameField: UITextField = {
        let field = UITextField()
        field.autocorrectionType = .no
        field.autocapitalizationType = .none
        field.returnKeyType = .continue
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "First Name"
        field.leftView = UIView(frame: CGRect(x: 0, y:0, width: 5, height: 0)) // padding
        field.leftViewMode = .always
        field.backgroundColor = .white
        return field
    }()

    private let lastNameField: UITextField = {
        let field = UITextField()
        field.autocorrectionType = .no
        field.autocapitalizationType = .none
        field.returnKeyType = .continue
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Last Name"
        field.leftView = UIView(frame: CGRect(x: 0, y:0, width: 5, height: 0)) // padding
        field.leftViewMode = .always
        field.backgroundColor = .white
        return field
    }()

    private let emailField: UITextField = {
        let field = UITextField()
        field.autocorrectionType = .no
        field.autocapitalizationType = .none
        field.returnKeyType = .continue
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Email Address"
        field.leftView = UIView(frame: CGRect(x: 0, y:0, width: 5, height: 0)) // padding
        field.leftViewMode = .always
        field.backgroundColor = .white
        return field
    }()

    private let passwordField: UITextField = {
        let field = UITextField()
        field.autocorrectionType = .no
        field.autocapitalizationType = .none
        field.returnKeyType = .done // enter: automatically login
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Password"
        field.leftView = UIView(frame: CGRect(x: 0, y:0, width: 5, height: 0)) // padding
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.isSecureTextEntry = true
        return field
    }()

    private let registerButton: UIButton = {
       let button = UIButton()
        button.setTitle("Sign Up", for: .normal)
        button.backgroundColor = .systemGreen
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 12
        button.layer.masksToBounds = true
        button.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Sign Up"
        view.backgroundColor = .white

        registerButton.addTarget(self,
                              action: #selector(registerButtonTapped),
                              for: .touchUpInside)
        emailField.delegate = self
        passwordField.delegate = self

        view.addSubview(scrollView)
        scrollView.addSubview(imageView)
        scrollView.addSubview(firstNameField)
        scrollView.addSubview(lastNameField)
        scrollView.addSubview(emailField)
        scrollView.addSubview(passwordField)
        scrollView.addSubview(registerButton)
        imageView.isUserInteractionEnabled = true
        //scrollView.isUserInteractionEnabled = true
        let gesture = UITapGestureRecognizer(target: self, action: #selector(didTapChangeProfilePic))
        imageView.addGestureRecognizer(gesture)
    }

    @objc private func didTapChangeProfilePic(){
        print("Change pic called")
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        scrollView.frame = view.bounds
        let size = scrollView.width/3
        imageView.frame = CGRect(x: (scrollView.width-size)/2,
                                 y: 20,
                                 width: size,
                                 height: size)
        firstNameField.frame = CGRect(x: 30,
                                  y: imageView.bottom+10,
                                  width: scrollView.width-60,
                                  height: 50)
        lastNameField.frame = CGRect(x: 30,
                                  y: firstNameField.bottom+10,
                                  width: scrollView.width-60,
                                  height: 50)
        emailField.frame = CGRect(x: 30,
                                  y: lastNameField.bottom+10,
                                  width: scrollView.width-60,
                                  height: 50)
        passwordField.frame = CGRect(x: 30,
                                  y: emailField.bottom+10,
                                  width: scrollView.width-60,
                                  height: 50)
        registerButton.frame = CGRect(x: 30,
                                  y: passwordField.bottom+10,
                                  width: scrollView.width-60,
                                  height: 50)
    }

    // validate text fields
    @objc private func registerButtonTapped(){

        emailField.resignFirstResponder()
        passwordField.resignFirstResponder()
        firstNameField.resignFirstResponder()
        lastNameField.resignFirstResponder()

        guard let firstname = firstNameField.text, let lastname = lastNameField.text,
              let email = emailField.text, let password = passwordField.text,
              !email.isEmpty, !password.isEmpty, //, password.count >= 6
              !firstname.isEmpty, !lastname.isEmpty
        else {
            alertUserLoginError()
            return
        }

        //firebase register
    }

    func alertUserLoginError(){
        let alert = UIAlertController(title: "Oops",
                                      message: "Please enter valid information",
                                      preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Dismiss",
                                      style: .cancel,
                                      handler: nil))
        present(alert, animated: true)
    }
}


extension RegisterViewController: UITextFieldDelegate{
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if textField == emailField {
            passwordField.becomeFirstResponder()
        }
        else if textField == passwordField {
            registerButtonTapped()
        }

        // true if the text field should implement its default behavior for the return button
        return true
    }
}

结语

今天写了很多程序,可喜可贺。
接下来终於要进到firebase的连线与服务了,好期待呀!

参考资料

文字输入 UITextField

若上述内容有误或可以改进的部分,欢迎留言以及提出任何指教~
谢谢 o(〃^▽^〃)o


<<:  15 修bug兼整理

>>:  Day 28 - 使用各种方式取得资料

#10 CSS3 Flexbox: nav style setting

What is nav? nav = navagator “The <nav> HTML...

Day 27 - Pwn 0x1

先欢迎各位来到整体难度最高的领域 在听这里之前 前面的逆向组语要先学好 还有对 OS 以及计算机概论...

TOGAF 的个 六个组件

[开放组] Open Group (http://www.opengroup.org/)架构框架 (...

Day 2 Docker 基本概念

在正式使用 docker 之前,需要先知道以下三个元素:映像档 ( Image )、容器 ( Con...

Day15|【Git】git reset 补充 - 三种模式

之前介绍 git reset 时,有提到说使用 git reset 指令时,有三种常用来搭配的参数模...