iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
自我挑戰組

來寫看看app好了! Swift探索之旅系列 第 14

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


上一篇
Day#13 登入畫面(2)
下一篇
Day#15 Firebase Auth
系列文
來寫看看app好了! Swift探索之旅30

尚未有邦友留言

立即登入留言