728x90
👨🏻💻 오늘의 작업
[ 1. TextField에 Extension 추가하기 ]



정산 1단계 상품 등록하기 부분에서 단위 입력과 금액 입력 TextField에 사용자가 값을 입력할 때
정수만 입력이 가능하도록 입력을 제한해야 한다.
해야 하는 것은 2가지 정도 된다.
사용자에게 입력을 받을 때 키보드 타입을 숫자패드로 변경하여 숫자만 입력할 수 있도록 유도한다.
그다음 TextField에 Extension을 추가해서 입력된 값이 Int값인지 검증하고 Int값이면 표시,
Int값이 아니면 입력되지 않게 처리하는 방법이 있다.
그러나 키보드 타입만 제한하는 방법에는 문제점이 있다.
바로 사용자가 복사 / 붙여 넣기 기능을 사용할 때이다.
외부에서 값을 복사 후 앱에서 붙여 넣기를 사용하면 키보드 타입을 넘버패드로 제한하여도 Int값이 아닌 String값이나
다른 값을 입력할 수 있는 문제가 있다.
해당 문제를 해결하기 위해 Extension까지 추가하는 방법이다.
나의 경우에는 RightViewTextField 컴포넌트에서만 사용할 예정이기 때문에
RightViewTextField에 Extension을 추가했다.
[ 1. 키보드 타입을 제한하기 ]
final class RightViewTextField: PaddedTextField {
init(rightText: String, keyboardType: UIKeyboardType = .numberPad) {
super.init(frame: .zero, fontStyle: body16)
self.keyboardType = keyboardType // 추가된 부분
configureUI(rightText: rightText)
}
[ 2. TextField에 Extension 추가하기 ]
extension Reactive where Base: RightViewTextField {
/// 천 단위 콤마가 포함된 숫자 텍스트
var formattedNumericText: ControlProperty<String> {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.groupingSeparator = ","
formatter.maximumFractionDigits = 0
let source = base.rx.text.orEmpty
.map { [weak base] text -> String in
guard let base = base else { return "" }
let numbers = text.filter { $0.isNumber }
guard !numbers.isEmpty, let value = Int(numbers) else {
if base.text != "" {
base.text = ""
}
return ""
}
let formatted = formatter.string(from: NSNumber(value: value)) ?? numbers
if base.text != formatted {
base.text = formatted
}
return numbers
}
let observer = Binder<String>(base) { textField, text in
let numbers = text.filter { $0.isNumber }
guard !numbers.isEmpty, let value = Int(numbers) else {
if textField.text != "" {
textField.text = ""
}
return
}
let formatted = formatter.string(from: NSNumber(value: value)) ?? numbers
if textField.text != formatted {
textField.text = formatted
}
}
return ControlProperty(values: source, valueSink: observer)
}
}
View에서 사용하기
// 등록하기 버튼 활성화 여부
Observable.combineLatest(
itemNameTextField.rx.text.orEmpty,
itemCountTextField.rx.formattedNumericText, // Extension 사용
itemAmountTextField.rx.formattedNumericText // Extension 사용
)
.map { !$0.0.isEmpty && !$0.1.isEmpty && !$0.2.isEmpty }
.bind(to: registerButton.rx.isEnabled)
.disposed(by: disposeBag)
// 등록하기 버튼 탭
registerButton.rx.tap
.withLatestFrom(
Observable.combineLatest(
itemNameTextField.rx.text.orEmpty,
itemCountTextField.rx.formattedNumericText, // Extension 사용
itemAmountTextField.rx.formattedNumericText // Extension 사용
)
)
.map { name, count, amount in
Reactor.Action.registerButtonTapped(name: name, count: count, amount: amount)
}
.bind(to: reactor.action)
.disposed(by: disposeBag)
728x90
'iOS 팀 프로젝트 > 소분해요' 카테고리의 다른 글
| 정산 2단계 구현하기 #1 (0) | 2026.01.12 |
|---|---|
| TextField에 Extension 추가하기 PR 작성 (1) | 2026.01.05 |
| PR 피드백 수정 및 코드 리뷰 #2 (0) | 2026.01.01 |
| PR 피드백 수정 및 코드 리뷰 (0) | 2025.12.26 |
| 정산 1단계 구현하기 #7 (0) | 2025.12.25 |