Rxswift Basic 2탄

Eddy📱·2022년 7월 12일
0

RxSwift

목록 보기
2/4
post-thumbnail

1탄에서는 Rxswift가 어떤식으로 동작되는지 파악할 수 있었다.

이제는 Rxswift에서 많이 사용하는 Operator의 내부를 파헤쳐보며 어떻게 동작하는지 확인해볼 것이다.

extension MyObservable {
    static func create(_ task: @escaping (_ execute: @escaping (T) -> Void) -> Void) -> MyObservable<T> {
        return MyObservable(task: task)
    }
}


MyObservable.create { execute in
    execute("\\(42)")
}
.subscribe { s in
    print(s)
}


// 42
스크린샷 2022-07-12 오후 1 12 37

이 메서드는 생성자를 받아서 여기에서 생성자를 호출하고 생성해주는 역할을 하고 있다.

그래서 return에서 MyObservable(task: task)로 호출하고 생성하는 것을 볼 수 있다.

실행하는 곳에서 보면 42라는 생성자를 호출해서 생성한 다음 subscribe에서 출력하는 것을 볼 수 있다.

extension MyObservable {
    static func just(_ value: T) -> MyObservable<T> {
        return MyObservable<T> { receiver in
            receiver(value)
        }
    }
}

MyObservable.just(42)
		.subscribe { i in print(i) }

// 42
스크린샷 2022-07-12 오후 1 12 54 `just`는 어떤 값을 받고 받은 것을 그대로 돌려주는 것을 의미한다. 그래서 `receiver`라는 용어라고 사용하고 있으며 받은 `value`를 바로 내보낸다. 이는 `task`를 대신 호출해주고 있다.

호출부에서 42를 받아서 바로 호출해주는 것을 볼 수 있다.

extension MyObservable {
    static func from(_ value: [T]) -> MyObservable<T> {
        return MyObservable<T> { receiver in
            value.forEach { t in
                receiver(t)
            }
        }
    }
}

MyObservable.from([42, 41, 40])
		.subscribe { i in
		    print(i)
		}

// 42
// 41
// 40
스크린샷 2022-07-12 오후 1 12 47

just에서는 값을 하나만을 전달하지만, from에서는 값을 여러번 전달할 수 있다.

내부를 보면 forEach로 반복문으로 내보내는 것을 볼 수 있다.

호출부에서 반복문으로 하나씩 출력되는 것을 볼 수 있다.

extension MyObservable {
    func map<U>(_ mapper: @escaping (T) -> U) -> MyObservable<U> {
        return MyObservable<U> { receiver in
            self.subscribe { t in
                receiver(mapper(t))
            }
        }
    }
}

MyObservable.from([41, 42, 43])
    .map { i in i * 2}
    .subscribe { s in
        print(s)
    }
// 82
// 84
// 86
스크린샷 2022-07-12 오후 1 13 07 `rxswift`에서 `map`는 `execute`로 생성해서 들어온 값을 새로 생성해준다. 그래서 `subscribe`를 해야 실제 값을 전달하게되고 새로 값을 만들어서 전달하게 된다.

그래서 값을 새로 만들어서 재설정 해줄 수 있다.

호출부에서 보면 2씩 곱해서 새로 만들어서 내보내는 것을 볼 수 있다.

extension MyObservable {
    func filter(_ filter: @escaping (T) -> Bool) -> MyObservable<T> {
        return MyObservable<T> { receiver in
            self.subscribe { t in
                if filter(t) {
                    receiver(t)
                }
            }
        }
    }
}

MyObservable.from([42, 41, 40])
		.filter { i in i % 2 == 0 }
		.map { i in "\\(i)" }
		.subscribe { i in
		    print(i)
		}

// 42
// 40
스크린샷 2022-07-12 오후 1 13 15 `filter`는 이름 그대로 걸러내준다! 그래서 내보낼지 말지는 `filter`의 조건에 따라 결정된다.

내부 코드를 보면 t가 나오는데 여기에서 조건문으로 filter(t)true라면 receiver에게 전달하고, 그게 아니라면 전달하지 않는다.

호출부에서 보게되면, 나머지가 0인 경우만 filter에서 true가 되어서 receiver에게 전달된다.

extension MyObservable {
    func flatMap<U>(_ mapper: @escaping (T) -> MyObservable<U>) -> MyObservable<U> {
        return MyObservable<U> { receiver in
            self.subscribe { t in
                mapper(t).subscribe { u in
                    receiver(u)
                }
            }
        }
    }
}

MyObservable.from([42, 41, 40])
        .filter { i in i % 2 == 0 }
        .flatMap { i in MyObservable.just(i) }
        .map { i in "\(i)" }
        .map { s in Int(s) }
        .filterNil()
        .main()
        .subscribe { i in
            print("flamap \(i)")
        }

// 42
// 40
스크린샷 2022-07-12 오후 1 13 01 `flatmap`는 `map`과의 차이점을 보게되면 `mapper` 파라미터의 반환값이 다른 것을 볼 수 있다.

동일하게 T를 받지만, map에서는 U를 내보내고, flatMap에서는 MyObservable<U>를 반환한다.

이 의미로는, value가 아니라 MyObservable<U> 반환값이 되어야 한다. 그래서 실제 가져온 값을 Observe해서 바꾼 값을 receiver에게 보내야 한다.

그래서 내부를 보면 subscribe를 두번하는 것을 볼 수 있다.

mapper로 이루어진 t를 다시 subscribe해서 나온 값을 receiver에게 전달하는 것을 볼 수 있다.

이름 그대로 더 평평하게 만들어준다는 것이다!

호출부를 보면 filter로 걸러준 다음 flatMap를 이용해서 값을 하나씩 보내도록 하고 이를 Int 타입으로 해서 내보내고 있다.

그래서 42, 40이 나오는 것이다.

extension MyObservable {
    func filterNil<U>() -> MyObservable<U> where T == U? {
        return filter { $0 != nil }.map { $0! }
    }
}

MyObservable.from([42, 41, 40])
		.filter { i in i % 2 == 0 }
		.flatMap { i in MyObservable.just(i) }
		.map { i in "\\(i)" }
		.map { s in Int(s) }
		.filterNil()
		.subscribe { i in
		    print(i)
		}

이 예시도 위에서 쓴 예시에서 사용한 것인데,

filterNil에 대해 설명하도록 하겠다.

여기에서는 T를 내보내는 것을 U 타입으로 바꾸게 된다.

그래서 T가 U타입의 Optional이면 Optional 뺀 것을 내보내겠다는 의미다.

그래서 nil이 아니면 강제추출하겠다는 의미다!

extension MyObservable {
    func main() -> MyObservable<T> {
        return MyObservable<T> { receiver in
            self.subscribe { t in
                DispatchQueue.main.async {
                    receiver(t)
                }
            }
        }
    }
}

MyObservable.from([42, 41, 40])
		.filter { i in i % 2 == 0 }
		.flatMap { i in MyObservable.just(i) }
		.map { i in "\\(i)" }
		.map { s in Int(s) }
		.filterNil()
		.main()
		.subscribe { i in
		    print(i)
		}

마지막으로는 Main Thread에서 실행되도록 만드는 코드다!

UI 작업과 같이 event 처리를 위해 Main thread로 설정해줘야 하는 경우가 있다.

내부를 보면 자신과 동일한 것을 return 하고 있는데

전달하는 부분인

self.subscribe { t in
    
}

이 부분에는 global thread로 보내고 그 내부에서 전달하는 것에서만 main thread로 보내도록 구현되어 있다.

그래서 동일한 예시에서 main thread로 보내야할 때 .main()를 사용해서 만들어주고 있다.

주요 기능들에 대해 한번 내부를 보고 실제 어떻게 동작하는지 확인해보았다!

다음에서는 Subject에 대해 알아볼 예정이다!

-참고사이트-
곰튀김님 강의
https://reactivex.io

profile
Make a better world

0개의 댓글