- isSecureTextEntry 활성화로 인하여 발생하는 입력값 초기화2025년 02월 10일 16시 02분 14초에 업로드 된 글입니다.작성자: 이중엽
개요
textField의 isSecureTextEntry를 활성화해주면 비밀번호와 같이 숨김 처리를 해야하는 정보들이 알아서 가림 처리가 된다.
그래서 보통 비밀번호 TextField는 위 프로퍼티를 꼭 활성화시켜주곤 한다.
다만 isSecureTextEntry를 활성화하면, TextField가 resigned된 이 후 다시 response가 발생했을 때 자동으로 입력값을 초기화시켜버린다.
위 영상처럼 해당 텍스트 필드를 벗어난 후 다시 입력할 때 다시금 입력해야하는 불편함이 발생했다.
그리고 이게 그렇게 자연스럽게 느껴지지 않는다.
해결 방법
솔직히 간단하게 끝날 줄 알았는데, 생각보다 오래걸렸다.
private var isEditingDidEnd: Bool = false let passwordStream = passwordTextField.rx.text.orEmpty .scan(("", "")) { previous, newText in return (previous.1, newText) } .share() let inputStream = passwordStream.filter { $0.count < $1.count } let deleteStream = passwordStream.filter { $0.count > $1.count } // 일반 입력 inputStream .bind(with: self) { owner, data in let (previous, newText) = data owner.isEditingDidEnd = false if previous == String() { let lastInput = owner.viewModel.fetchInputPassword() owner.passwordTextField.text = lastInput + newText owner.viewModel.inputPasswordEvent.accept(lastInput + newText) } else { owner.viewModel.input.inputPasswordEvent.accept(newText) } } .disposed(by: disposeBag) // 백스페이스 deleteStream .map { previous, newText in return newText } .bind(with: self) { owner, newText in if owner.isEditingDidEnd, newText.count == Int() { return } owner.viewModel.input.inputPasswordEvent.accept(newText) } .disposed(by: disposeBag) // 편집 완료 passwordTextField.rx.controlEvent(.editingDidEnd) .bind(with: self) { owner, _ in owner.isEditingDidEnd = true } .disposed(by: disposeBag) 우선 scan과 share 그리고 filter를 통해 inputStream과 deleteStream을 구분해주었다.
여기서 또 한가지 문제는 초기화가 될 때도 deleteStream으로 값이 넘어왔다.
초기화가 되면서 previous보다 newText가 작았기 때문이다.
이러면 backSpcace와 초기화로 인한 차이를 구분할 수가 없다.
그래서 controlEvent로 editing이 끝나는 이벤트가 발생할 때 만들어둔 변수 isEditingDidEnd를 true로 바꿔줌으로써 이를 활용하여 backSpace와 초기화를 구분할 수 있게 되었다.
input에서는 isEditingDidEnd를 입력이 발생하면 false로 바꾸어준다.
output에서는 isEditingDidEnd일때는 isSecureTextEntry로 인한 초기화이기 때문에 해당 이벤트를 무시한다.
순서 상 input이 먼저 false로 바꿔버려서 output이 동작할 때 그대로 통과하면 어떡하냐 할 수있지만,
input과 delete는 share에서 분기된 stream이기 때문에 순서와 상관없이 동일한 이벤트를 전달받는다.
마지막으로 input에서는 초기화 이벤트를 감지하지 못하기 때문에, previous가 String() 즉 초기화되어있을 때 마지막 입력값을 가져와서 새로운 입력과 합쳐준다.
여기서 text에 다시 주입하면 결국 다시 rx.text가 실행되어서 무한루프에 빠지지 않을 까 할 수 있지만,
rx.tex는 직접적인 값 주입에는 반응하지 않고 오로지 유저가 입력하거나 하는 이벤트에만 동작한다.
이 부분은 나중에 다시 다뤄보겠다
'TroubleShooting' 카테고리의 다른 글
[TS] CollectionView.rx.itemSelected가 먹통이 된 이유 (0) 2025.02.09 다음글이 없습니다.이전글이 없습니다.댓글