RxSwift 입문(1) 에서 DisposeBag까지 알아보았다.
이번에는 Operator들에 대해서 공부해보려고 한다.
공식 홈페이지 문서에 보면 Operator 에 대한 설명이 뭐라뭐라 나와있다. 하지만 솔직히 말하자면, Operator을 처음 접하는 내 입장에서는 정확하게 이해하기 어렵다.
그냥 예문을 통해서 Operator가 무엇인지 살펴보자.
@IBAction func exJust1() {
Observable.just("Hello World")
.subscribe(onNext: { str in
print(str)
})
.disposed(by: disposeBag)
}
Operator 중 Just 에 대한 예문이다.
Just는 () 안에 객체를 그대로 가져온다.
결과는
로 예상 가능하다.
@IBAction func exJust2() {
Observable.just(["Hello", "World"])
.subscribe(onNext: { arr in
print(arr)
})
.disposed(by: disposeBag)
}
Just를 Array에 적용시켰다.
크게 다르지 않다.
@IBAction func exFrom1() {
Observable.from(["RxSwift", "In", "4", "Hours"])
.subscribe(onNext: { str in
print(str)
})
.disposed(by: disposeBag)
}
이번엔 From에 대해 알아보자.
결과가 다음과 같은 것으로 보아
Just와 달리 From은 Array 안에 객체를 각각 받아오는 것으로 유추할 수 있다.
@IBAction func exMap1() {
Observable.just("Hello")
.map { str in "\(str) RxSwift" }
.subscribe(onNext: { str in
print(str)
})
.disposed(by: disposeBag)
}
Mapping
여기서 .map 이 나온다.
Swift 언어로 알고리즘 공부를 하다가 Programmers 에서 문제를 풀기 시작했었는데, 해답을 보니 짧고 간단한 코드들은 모두 Map() 이라는 함수가 들어갔던 것으로 기억한다.
Just 의 "Hello" 를
map 에서 str로 받아와 in "(str) RxSwift" 에 적용 시킨 후
subscribe 에서 print 해준다.
Q1. 코드 끝에 disposed를 없애면 어떻게 될까?
없애기 전.
없앤 후.
결과는 차이가 없지만
코드에서,
에러가 나오는데,
.subscribe를 사용하고 나면 dispose 되었을 때 이벤트를 적어주라는 경고이다.
일단은 이 에러가 나오는 것 말고는 큰 차이는 없다.
더 공부하다보면 나올 것 같다.
Q2. .subscribe를 사용하지 않고 구현해보면?
먼저 subscribe를 제거하고 코드를 짜 보았다.
@IBAction func exMap1() {
Observable.just("Hello")
.map { str in "\(str) RxSwift" }
.map { str in print(str) }
}
결과로는 아무것도 print 되지 않는다.
다음으로는, print를 subscribe가 아니라 map 에서 해줬다.
@IBAction func exMap1() {
Observable.just("Hello")
.map { str in "\(str) RxSwift" }
.map { str in print(str) }
.subscribe(onNext: { Void in
})
.disposed(by: disposeBag)
}
출력이 정상적으로 되는 것을 볼 수 있다.
위의 두 가지 호기심으로 알 수 있었던 것은
Observable 은 항상 끝에 subscribe로 끝나야 하는 것 같다.
그리고 가면 갈 수록 SwiftUI와 굉장히 비슷하다는 생각이 든다.
@IBAction func exMap2() {
Observable.from(["with", "shawn"])
.map { $0.count }
.subscribe(onNext: { str in
print(str)
})
.disposed(by: disposeBag)
}
from으로 받아온 array 전체 ( $0 ) 를 .count 해서 출력한다.
@IBAction func exFilter() {
Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.filter { $0 % 2 == 0 }
.subscribe(onNext: { n in
print(n)
})
.disposed(by: disposeBag)
}
from으로 받아온 array 중 .filter 안에 true 인것만
.subscribe 의 n 안에 넣어준다.
2, 4, 6, 8, 10이 출력된다.
@IBAction func exMap3() {
Observable.just("800x600")
.map { $0.replacingOccurrences(of: "x", with: "/") }
.map { "https://picsum.photos/\($0)/?random" }
.map { URL(string: $0) }
.filter { $0 != nil }
.map { $0! }
.map { try Data(contentsOf: $0) }
.map { UIImage(data: $0) }
.subscribe(onNext: { image in
self.imageView.image = image
})
.disposed(by: disposeBag)
}
제일 중요한 예문인데,
800x600 에서 x 를 /로 바꾼다. ( replacingOccurrences 를 이용 )
이미지 url 에서 800/600 사이즈의 이미지를 찾아오는 코드인 것 같다.
url 을 URL 로 바꾸고,
nil 이 아닌 것을 filter 해주고 (예외처리 인 것 같다 )
UIImageview에 넣기 위해 Data로 바꿔주고 이미지를 띄워주면 끝.
What's New?
앱 개발자들을 필요로하는 스타트업들을 찾아보니, 대부분이 iOS Android를 함께 만들기 위해 ReactiveNative 같은 하이브리드 앱 개발자들을 많이 찾는다. (결국 회사가 성장함에 따라 네이티브로 바뀌겠지만)
애플 또한 SwiftUI로 갈아타게끔 하려는 추세인 지금
반응형 프로그래밍을 제대로 아는것이 너무 중요한 것 같다.
오늘 배운 7가지 예문들을 보면
SwiftUI 와 매우 비슷하게 흘러가면서
ㅊㅊ: 리액티브 공식 홈페이지
Observable Stream이라는게 뭔지 감을 잡을 수 있었다.