Rx 이벤트 처리 문제 풀기
Rx 이벤트 처리 문제 풀기
📌 1번: 버튼 클릭 이벤트 처리
문제 내용
- 버튼(
UIButton
)을PublishSubject<Void>
로 감싸서 Rx 방식으로 클릭 이벤트를 처리하라. - 버튼이 클릭될 때마다
"버튼이 클릭됨"
이라는 문자열을 출력하라. - 버튼을 3번 클릭하면
"버튼이 3번 클릭됨"
이라는 메시지를 출력하라.
정답 코드
1
2
3
4
5
6
7
8
9
10
11
12
let button = UIButton()
button.rx.tap
.scan(0) { count, _ in count + 1 }
.subscribe(onNext: { count in
if count == 3 {
print("버튼이 3번 클릭됨")
} else {
print("버튼이 클릭됨")
}
})
.disposed(by: disposeBag)
문제 해설
.scan(0) { count, _ in count + 1 }
→ 클릭 횟수를 누적함.- 버튼을 클릭할 때마다 1씩 증가하고, 3번 클릭 시 특정 메시지를 출력함.
📌 2번: 텍스트 입력 감지하기
문제 내용
UITextField
를 생성하고, 사용자가 입력한 내용을 감지하라.- 입력할 때마다 입력된 텍스트를 출력하라.
- 입력된 텍스트가
"RxSwift"
가 되면"RxSwift 입력 완료"
를 출력하라.
정답 코드
1
2
3
4
5
6
7
8
9
10
11
textField.rx.text
.compactMap { $0 } // 옵셔널 제거
.subscribe(onNext: { value in
if value == "RxSwift" {
print("RxSwift 입력 완료")
} else {
print(value)
}
})
.disposed(by: disposeBag)
문제 해설
.compactMap { $0 }
→UITextField.rx.text
는Observable<String?>
이므로 nil 값을 제거해야 한다.- 입력된 텍스트가
"RxSwift"
가 되면"RxSwift 입력 완료"
메시지를 출력함.
📌 3번: API 호출 후 UI 업데이트하기
문제 내용
- 버튼을 클릭하면 네트워크 요청(
Observable<String>
)을 수행하는 코드를 작성하라. - 네트워크 요청이 완료되면 결과를
UILabel
에 표시하라. - 버튼을 여러 번 클릭해도 동시에 여러 개의 요청이 발생하지 않도록 처리하라.
정답 코드
1
2
3
4
5
6
7
let network: Observable<String> = Observable.just("네트워크 응답")
button.rx.tap
.withLatestFrom(network)
.bind(to: label.rx.text)
.disposed(by: disposeBag)
문제 해설
.withLatestFrom(network)
→ 버튼을 클릭할 때마다 네트워크의 최신 값 가져옴..bind(to: label.rx.text)
→ 네트워크 응답을 UILabel에 표시함.- 이전 요청이 끝나지 않았을 때 중복 요청을 막을 필요가 있으면
flatMapLatest
를 사용해야 함.
📌 4번: 중복 네트워크 요청 방지하기
문제 내용
- 버튼을 클릭할 때마다 네트워크 요청(
Observable<String>
)을 수행하라. - 네트워크 요청이 진행 중이면 새로운 요청을 무시하도록 처리하라.
- 네트워크 요청이 완료되면 버튼을 다시 클릭할 수 있도록 하라.
정답 코드
1
2
3
4
5
6
7
8
9
func networkRequest() -> Observable<String> {
return Observable.just("네트워크 응답")
}
button.rx.tap
.flatMapLatest { networkRequest() }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
문제 해설
.flatMapLatest { networkRequest() }
→ 이전 요청이 끝나지 않았을 때, 새로운 요청을 무시함.- 버튼 클릭 시 네트워크 요청을 수행하고 응답을 출력함.
📌 5번: 입력 필드와 버튼을 조합하여 검색 요청 만들기
문제 내용
UITextField
에 입력된 값을UIButton
을 클릭했을 때만 가져와 출력하라.- 버튼을 클릭하면 입력된 텍스트를 네트워크 요청(
Observable<String>
)으로 변환하라. - 입력 값이 바뀌더라도, 버튼을 클릭해야만 네트워크 요청이 실행되도록 하라.
정답 코드
1
2
3
4
5
6
7
8
let network = { (query: String) in Observable.just("검색 결과: \(query)") }
button.rx.tap
.withLatestFrom(textField.rx.text.orEmpty)
.flatMapLatest { network($0) }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
문제 해설
.withLatestFrom(textField.rx.text.orEmpty)
→ 버튼을 클릭할 때, 입력된 텍스트를 가져옴..flatMapLatest { network($0) }
→ 입력된 텍스트를 네트워크 요청으로 변환함.
📌 6번: map
연산자 응용 (문자열 길이 변환)
문제 내용
Observable<[String]>
을 생성하여["Apple", "Banana", "Cherry"]
배열을 방출하라.map
을 사용하여 각 문자열을 해당 문자열의 길이(Int)로 변환하라.
정답 코드
1
2
3
4
5
Observable.just(["Apple", "Banana", "Cherry"])
.map { $0.map { $0.count } }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
문제 해설
- 배열 내부의 각 문자열을 개별적으로 변환하려면
map
을 두 번 사용해야 한다. "Apple" → 5
,"Banana" → 6
,"Cherry" → 6
으로 변환됨.
📌 7번: filter
연산자 응용 (짝수만 필터링)
문제 내용
Observable<[Int]>
을 생성하여[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
배열을 방출하라.filter
를 사용하여 짝수만 출력하라.
정답 코드
1
2
3
4
5
Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.filter { $0 % 2 == 0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
문제 해설
Observable.from()
을 사용하면 배열을 개별 요소로 변환하여 방출할 수 있음.filter
를 적용하면 짝수만 출력됨.
📌 8번: scan
을 활용한 중복된 검색어 요청 방지
문제 내용
UITextField
에서 입력한 텍스트를 실시간으로 감지하라.- 입력된 텍스트가 이전 값과 같다면 요청을 보내지 않도록 처리하라.
정답 코드
1
2
3
4
5
6
7
8
9
10
11
swift
복사
let network = { (query: String) in Observable.just("검색 결과: \(query)") }
textField.rx.text
.compactMap { $0 }
.scan("") { before, current in before == current ? before : current }
.flatMapLatest { network($0) }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
문제 해설
.scan("", { before, current in ... })
→ 이전 값과 비교하여 변경된 값만 전달함..flatMapLatest { network($0) }
→ 변경된 값만 네트워크 요청을 보냄.
📌 9번: 버튼 클릭 후, 5초 동안 추가 클릭 방지하기
문제 내용
- 버튼 클릭 시
"요청 보냄"
을 출력하라. - 클릭 후 5초 동안 버튼을 비활성화하여 추가 클릭을 방지하라.
- 5초가 지나면 버튼을 다시 활성화하라.
정답 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
swift
복사
let button = UIButton()
let isEnabled = BehaviorRelay<Bool>(value: true) // 버튼 활성화 상태 관리
button.rx.tap
.withLatestFrom(isEnabled)
.filter { $0 } // 버튼이 활성화된 경우에만 실행
.do(onNext: { _ in isEnabled.accept(false) }) // 클릭 후 비활성화
.map { "요청 보냄" }
.subscribe(onNext: {
print($0)
isEnabled.accept(true) // 5초 후 버튼 다시 활성화
})
.disposed(by: disposeBag)
문제 해설
.withLatestFrom(isEnabled)
→ 현재 버튼 상태를 확인하고, 활성화된 경우만 실행.do(onNext: { _ in isEnabled.accept(false) })
→ 버튼 클릭 후 비활성화(false
)로 설정.map { "요청 보냄" }
→ 출력값 변환.subscribe(onNext: { ... isEnabled.accept(true) })
→ 출력 후 버튼 다시 활성화
📌 10번: filter
를 활용한 짝수 필터링
문제 내용
Observable<[Int]>
을 생성하여[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
배열을 방출하라.filter
를 사용하여 짝수만 출력하라.
정답 코드
1
2
3
4
5
6
7
swift
복사
Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.filter { $0 % 2 == 0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
문제 해설
Observable.from()
을 사용하여 배열을 개별 요소로 변환.filter { $0 % 2 == 0 }
→ 짝수만 필터링하여 출력
This post is licensed under CC BY 4.0 by the author.