iOS_ Handling Text and Font (2)

longlivedrgn·2022년 11월 1일
0

iOS 스터디

목록 보기
4/8
post-thumbnail

TextDelegate

  • 아래와 같이 storyboard와 outlet을 설정하였다.

  • 각각 textField는 아래와 같이 설정을 할 수 있다.

  • 마지막 emailTextField만 아래와 같이 설정을 한다.

  • namefield는 10자리만 입력이 가능하게, ageField는 1~100만 입력이 가능하게, genderfield는 M or F만 입력이 가능하게, emailField는 포멧에 맞게만 입력이 가능하게 설정을 하기

import UIKit

class TextDelegateViewController: UIViewController {
    
    @IBOutlet weak var nameField: UITextField!
    
    @IBOutlet weak var ageField: UITextField!
    
    @IBOutlet weak var genderField: UITextField!
    
    @IBOutlet weak var emailField: UITextField!
    
    // 이메일의 포멧이다!
    let regex = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
    
    // 숫자제외 모든 문자를 set으로 생성
    lazy var charSet = CharacterSet(charactersIn: "0123456789").inverted
    
    // MF제외 모든 문자를 set으로 생성
    lazy var invalidGenderCharSet = CharacterSet(charactersIn: "MF").inverted
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // 바로 편집모드로 설정한다.
        nameField.becomeFirstResponder()
    }
}

extension TextDelegateViewController: UITextFieldDelegate{
    
    // return 키를 누르면 다음 textfield로 넘어가게 하기
    // textfield에서 return 키가 눌러지면 해당 함수가 실행이된다.
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        
        switch textField {
        case nameField:
            ageField.becomeFirstResponder()
        case ageField:
            genderField.becomeFirstResponder()
        case genderField:
            emailField.becomeFirstResponder()
        case emailField:
            emailField.resignFirstResponder()
        default:
            break
        }
        return true
    }
    
    // namefield에 들어가는 글자를 최대 10자로 해보자
    // ageField에는 최대한 1~100만 입력할 수 있도록 해보기
    // genderField에는 문자 M F만 입력할 수 있도록 해보기
    // emailField에는 email만 입력이 가능하게 해보기
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // 추가되긴 전 text
        print("current: \(textField.text ?? "")")
        // string -> 새롭게 추가될 문자
        print("string: \(string)")
        
        // textfield.text를 nsstring으로 만들어준다.
        let currentText = NSString(string: textField.text ?? "")
        let finalText = currentText.replacingCharacters(in: range, with: string)
        
        switch textField {
        case nameField:
            if finalText.count > 10{
                // 입력된 내용을 무시한다. 즉 추가가되지 않는다.
                return false
            }
            
        case ageField:
            
            // charSet에 없는 문자는 싹 다 제한을 시킨다!
            if let _ = string.rangeOfCharacter(from: charSet){
                return false
            }
            if let age = Int(finalText), !(1...100).contains(age) {
                return false
            }
            
        // 글자도 한개만 가능하게, 그리고 MF만 입력이 가능하도록!
        case genderField:
            if let _ = string.rangeOfCharacter(from: invalidGenderCharSet){
                return false
            }
            
            if finalText.count > 1 {
                return false
            }


        default:
            break
        }
        
        // true가 나와야지 textfield에서 최종적으로 추가가 된다.
        return true
    }
    
    // Email을 맞는 포멧에만 입력이 가능하게!
    // true를 return하면 편집상태를 종료한다!
    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
        if textField == emailField {
            
            // 잘못된 email format일 경우 return false를 한다!
            guard let email = textField.text, let _ = email.range(of: regex, options: .regularExpression) else {
                alert(message: "invalid email")
                return false
            }
        }
        return true
    }
}

extension TextDelegateViewController {
    func alert(message: String) {
        let alert = UIAlertController(title: "알림", message: message, preferredStyle: .alert)
        
        let ok = UIAlertAction(title: "확인", style: .default, handler: nil)
        alert.addAction(ok)
        
        present(alert, animated: true, completion: nil)
    }
}

Input View & Input Accessory View

Agefied에 pickerview 넣기

  • 아래와 같이 uiview를 dock에 넣어서 추가해주고 그 안에 pickerview를 추가해준다.

  • 그리고 pickerview를 본 view에 datasource와 delegate으로 연결해준다.

  • Pickerview가 추가된 view를 outlet으로 설정해준다.

    @IBOutlet var pickerContainterView: UIView!
  • 그리고 datasource와 delegate protocol을 만족시켜준다.
extension InputViewViewController: UIPickerViewDataSource {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return 100
    }
}

extension InputViewViewController: UIPickerViewDelegate {
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return "\(row + 1)"
    }
    // 선택되면 해당 ageField.text를 변경해주기
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        ageField.text = "\(row + 1)"
    }
}
  • 최종적으로 ageField에 pickerview를 input해준다.
    override func viewDidLoad() {
        super.viewDidLoad()
        
        ageField.inputView = pickerContainterView
        
    }

genderView에 buttonview 넣기

  • 앞선 pickerview와 동일하게 새로운 view를 만들어준다.

  • f button의 태그를 1로 바꿔줘서 m과 구별할 수 있게 해준다.

  • outlet으로 추가해준다.

    @IBOutlet var buttonContainerView: UIView!
  • selectGender 함수를 두 button에 다 연결시켜준다.
    @IBAction func selectGender(_ sender: UIButton) {
        genderField.text = sender.tag == 0 ? "M" : "F"
        UIDevice.current.playInputClick()
    }
  • 그리고 viewDidLoad에 추가해주기
        genderField.inputView = buttonContainerView

모든 field에 툴바 넣어주기

  • 앞선 예와 비슷한 방식을 통하여 아래와 같이 toolbar를 추가해주기
  • 툴바를 outlet으로 설정해주기
    @IBOutlet var accessoryBar: UIToolbar!
  • viewDidLoad에 넣어주기
        ageField.inputAccessoryView = accessoryBar
        genderField.inputAccessoryView = accessoryBar
        nameField.inputAccessoryView = accessoryBar
  • textfield 포커스를 이동시켜주는거 구현하기
@IBAction func movePrevious(_ sender: Any) {
        if genderField.isFirstResponder {
            ageField.becomeFirstResponder()
        } else if ageField.isFirstResponder {
            nameField.becomeFirstResponder()
        }
    }
    
    @IBAction func moveNext(_ sender: Any) {
        if nameField.isFirstResponder {
            ageField.becomeFirstResponder()
        } else if ageField.isFirstResponder{
            genderField.becomeFirstResponder()
        }
    }

0개의 댓글