UITextField는 재미있는 친구다.
이 친구를 더욱 다양한 방법으로 활용하기 위해서는 UITextFieldDelegate 프로토콜을 추가해주어야 한다.
그런다음 textField.delegate = self 로 상속받기.
굉장히 간단한 쇼핑 리스트 앱을 만들어보고자 했지만, 생각보다 UITextField를 다루기가 쉽지 않았다.
보통은 새로운 창을 띄워 텍스트를 입력하고 저장하면 목록에서 볼 수 있도록 하는 방법으로 text field를 많이 사용하지만,
새로운 창 같은거 띄우지 않고 그냥 테이블뷰 목록에서 직접 입력하고 편집하고 값 저장하고 다 하려니까 UITextFieldDelegate에 대해 아주 깊게 탐구해보게 되었다.
애플 개발자 문서를 찾아보면
<UITextFieldDelegate> 란?
키보드 입력 및 전반적인 text field 편집과 관련된 기능들을 수행하는 프로토콜이라고 한다.
텍스트필드 편집 과정의 흐름을 살펴보면,
1. textFieldShouldBeginEditing(_:)
2. text field가 활성화 되면 텍스트 입력을 위한 키보드 생성
(보통 해당 text field를 터치하면 바로 활성화가 되지만, 터치 하기 전에 자동으로 text field 입력을 시작하도록 키보드를 띄우고 싶다면 textField.becomeFirstResponder() 를 선언해주면 된다.)
3. textFieldDidBeginEditing(_:)
4. text field 편집 중에 호출되는 다양한 delegate 메서드들
그 중, textFieldShouldReturn(_:)은 사용자가 키보드의 return 버튼을 탭 했을 때 호출되는 함수로 꽤 유용하게 쓰인다.
5. textFieldShouldEndEditing(_:)
6. text field 비활성화 하고 키보드 숨기기 (textField.resignFirstResponder() 로 직접 호출 가능)
7. textFieldDidEndEditing(_:)
내가 사용한 기능들
** start editing UITextField and show keyboard
먼저 항목 추가 버튼을 눌러 새로운 테이블뷰 셀이 생성되면, 자동으로 text field가 활성화되고 키보드가 올라오게 하기 위해서
tableView의 cellForRowAt indexPath 함수에 다음을 추가해주었다.
textField.becomeFirstResponder()
** keyboard dismiss with return Button
키보드의 입력 완료 버튼을 눌렀을때 키보드가 사라지게 하고 싶다면 UITextFieldDelegate 프로토콜을 상속받은 클래스 안에
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
** keyboard dismiss by touching anywhere in the view
화면 아무데나 터치 해도 키보드가 사라지게 하고 싶다면
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
super.touchesBegan(touches, with: event) //
self.view.endEditing(true)
}
이방법을 쓰면 된다고 많이 나와 있던데 나는 안되더라. 읭?.?
그래서 다음 코드를 viewDidLoad에 추가해주었더니 잘 되더라. 화면 아무데나 터치하면 endEditing이 호출되도록 해서 키보드를 없애주었다.
let tapGesture = UITapGestureRecognizer(target: view, action: #selector(view.endEditing))
view.addGestureRecognizer(tapGesture)
** save UITextField text into UITableView cell
텍스트를 완료한 후 입력 버튼을 누르거나 화면 아무데나 터치하면, 입력된 텍스트를 해당 cell 저장하기 위해 다음과 같이 작성해주었다.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
let textFieldIndexPath = self.tag
endTextEdit(textField.text ?? "", textFieldIndexPath)
}
func endTextEdit(_ text: String, _ tag: Int) {
items[tag] = text
tableView.reloadData()
}
위의 두 함수는 UITextFieldDelegate 프로토콜에서 상속받은 내장 함수로,
첫 번째 함수에서는 사용자가 키보드의 return 버튼을 눌렀을 때 .resignFirstResponder() 메서드를 호출하여 키보드가 사라지도록 했다.
두 번째 textFieldDidEndEditing() 함수는 .resignFirstResponder() 가 호출되었을 때 호출되는 함수로, 화면을 탭하여 text field가 비활성화 되거나, 키보드의 return을 눌러 입력을 비활성화 했을 때 작동한다. 그래서 나는 이 함수로부터 해당 UITextField의 tag 값과 text를 받아와서, 마지막 endTextEdit 함수에 값을 넘겨주고 reloadData() 를 해주었다.
+ 키보드 입력에 실시간으로 반응하고 싶다면?
@objc func textFieldDidChange(_ textField: UITextField) {
// 키보드 업데이트 시 원하는 기능
}
키보드 업데이트시 작동시킬 @objc 함수를 만들어주고, textField에 .editingChanged 라는 UIControl Event로 함수를 작동시키면 키보드 입력을 실시간으로 반영할 수 있다.
textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
Q. UITapGestureRecognizer를 사용하여 입력을 비활성화한 후 입력받은 텍스트를 저장할 경우 생기는 문제점?
작동 자체에는 문제가 없다. 그런데 화면 탭 시 textFieldDidEndEditing을 불러올경우, 화면에서 항목 추가 버튼을 좀만 길게 눌러도 함수가 여러번 계속 호출이 되더라. 작동에는 문제가 없이 잘 돌아가지만, 배열의 값이 계속 바뀌고 reloadData() 가 여러번 된다면 불필요하게 에너지를 낭비하게 되는 것 같다. 이를 어떻게 방지하나...
'Project > ToyProject_Shopping List' 카테고리의 다른 글
[Toy Project] Shopping List 장보기 앱 만들기 (0) | 2021.03.23 |
---|