operator

Observable이 수행하는 메소드. Observable에서 파생되는 스트림을 구성하는 rxSwift의 핵심요소라고 할 수 있다. 

Observable에는 수행가능한 여러가지 operator가 있는데, 그중 대표적인것들에 대해서 적어보려고 한다. 

 

just()

static func just(_ element: [String]) -> Observable<[String]>
//returns an Observable sequence that contains a single element
Observable.just(_ element: )

입력 요소에 대해 그대로 반환되는 연산자이다. 예시를 통해 보자. 

@IBAction func exJust1() {
    Observable.just("Hello World")
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//Hello World!    출력

@IBAction func exJust2() {
    Observable.just(["Hello", "World"])
        .subscribe(onNext: { arr in
            print(arr)
        })
        .disposed(by: disposeBag)
}
//["Hello","World"]    출력

배열을 넣어도 배열이 통째로 출력되는 모습을 볼 수 있다.


from()

public static func from(_ array: [Element]) -> Observable<Element>
//Converts an array to an observable sequence.
Observable.from(_ array: [_])

배열의 원소들을 Observable의 형태로 리턴해준다.

@IBAction func exFrom1() {
    Observable
        .from(["RxSwift", "In", "4", "Hours"])
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//RxSwift
//In
//4
//Hours 출력

from을 통해 나오는 Observable<String>형태의 원소들이 subscribe(OnNext: )부분에서 출력이 된다.


map()

func map<Result>(_ transform: @escaping (String) throws -> Result) -> Observable<Result>
//Projects each element of an observable sequence into a new form.

swift에서의 map()과 같은 동작을 하는 operator이다. Observable에서 생성되어 내려오는 데이터들에 closure에 적힌 동작에 따라 가공하여 리턴해준다. 

@IBAction func exMap1() {
    Observable.just("Hello")
        .map { str in "\(str) RxSwift" }
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//Hello RxSwift 출력

@IBAction func exMap2() {
    Observable.from(["RxSwift", "ReactiveX"])
        .map { $0.count }
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//7
//9 출력

아마도 가장 많이 쓰게될 operator가 아닐까 생각된다.


filter()

func filter(_ predicate: @escaping (Int) throws -> Bool) -> Observable<Int>
//Filters the elements of an observable sequence based on a predicate.

swift의 filter()함수와 동일하게 동작하는 오퍼레이터이다. 서술한 조건에 맞는 경우에만 Observable을 내보낸다.

@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)
}
//2
//4
//6
//8
//10 출력

배열요소들 중에 짝수인 요소만 출력된다.


stream

우리는 이러한 여러가지 오퍼레이터들을 통해 Observable을 가공하여 비동기 프로그래밍을 할 수 있게 된다. 앞의 글에서도 설명했지만 이러한 가공의 과정을 stream이라 부르기로 했고, 이러한 Observable을 통한 stream을 통해 비동기 프로그래밍을 할 수 있게 해주는 것이 RxSwift이다.

@IBAction func exMap3() {
    Observable.just("800x600")
        .map { $0.replacingOccurrences(of: "x", with: "/") }    //"800/600"
        .map { "https://picsum.photos/\($0)/?random" }          //"https://picsum.photos/\800/600/?random"
        .map { URL(string: $0) }                                //URL?
        .filter { $0 != nil }
        .map { $0! }                                            //URL!
        .map { try Data(contentsOf: $0) }                       //Data
        .map { UIImage(data: $0) }                              //UIImage?
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposeBag)
}

Observable이 여러가지 오퍼레이터를 통해 어떤식으로 변화하는지 주석으로 적어놓았다. 

 

이외에도 정말 많은 오퍼레이터들이 있으며, 사용처에 따라 알맞은 오퍼레이터를 사용하면 된다. 각 오퍼레이터에 대한 상세한 내용들도 홈페이지에서 열람 가능하다.

 

[참고영상]

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 4

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 5

'iOS > RxSwift' 카테고리의 다른 글

scheduler  (0) 2022.08.31
next, error, complete  (0) 2022.08.19
subscribe, dispose  (0) 2022.06.15
Observable stream  (0) 2022.06.08
ReactiveX  (0) 2022.05.30

operator

연산자(operator)는 항을 재료로 계산 후 결과를 반환해주는 것이다. 연산자에 의해 연산되는 값의 수에 따라 단항, 이항, 삼항 등으로 구분하기도 하며, 연산자의 위치에 따라 전위, 중위, 후위 등으로 구분하기도 하는데, 그 중에서도 오늘은 이항연산자와 삼항 연산자에 대해 알아보도록 한다. 

 

산술 연산자

이항 연산자의 한 종류이다. 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지 계산이 가능하다.

var a = 20, b = 3

print("a+b: \(a+b)")
print("a-b: \(a-b)")
print("a*b: \(a*b)")
print("a/b: \(a/b)")
print("a%b: \(a%b)")

문자열에는 덧셈연산이 결합연산으로 적용된다. 

var x = "맛있는"
var y:String = "피자"

print("x: \(x)")
print("y: \(y)")
print("x+y: \(x+y)")

한가지 주의해야 할 점은 스위프트의 연산자는 다른 언어와 달리 같은 자료형이어야만 동작한다는 점이다. 따라서 다른 자료형끼리 연산을 할 때에는 자료형 변환을 통해서 자료형을 맞추어 주어야 한다. 산술연산에는 당연히 계산 우선순위가 존재한다. 

 

비교 연산자

Bool을 반환하는 이항연산자이다. 초과, 미만, 이상, 이하, 같다, 다르다를 비교하여 결과값으로 bool형을 반환한다. 

a=10; b=20

print(a , ">", b, ":", a > b)
print(a , "<", b, ":", a < b)
print(a , ">=", b, ":", a >= b)
print(a , "<=", b, ":", a <= b)
print(a , "==", b, ":", a == b)
print(a , "!=", b, ":", a != b)

문자열의 비교도 가능하다. 가나다 순으로 비교를 하며 후위의 글자가 더 높은 것으로 판단한다. 앞글자가 같다면 글자수가 더 많은 글자가 더 높은 것으로 판단한다.

x = "정우성" ; y = "정좌성"

print(x , "<", y, ":", x < y)
print(x , ">", y, ":", x > y)
print(x , "<=", y, ":", x <= y)
print(x , ">=", y, ":", x >= y)
print(x , "==", y, ":", x == y)
print(x , "!=", y, ":", x != y)

bool간의 비교는 ==, != 연산만 가능하다. 

var  qq = true , ww = false

print(qq, "==", ww, ":", qq == ww)
print(qq, "!=", ww, ":", qq != ww)

 

논리 연산자

bool연산자 라고도 한다. AND, OR, NOT 연산이 있다. 

AND 연산은 두 항의 값이 true여야만 true를 반환하며 그외에는 false만 반환한다.  &&로 표현한다.

OR 연산은 두 항의 값이 하나만 true이면 true를 반환한다. 두 항의 값이 false여야만 false를 반환한다.  ||로 표현한다.

NOT 연산은 단항 연산자이다. 항의 값을 반전시켜준다. true를 false로 false를 true로 반환한다.  !로 표현한다.

qq = true ; ww = false

print(qq, "&&", ww, ":", qq && ww)
print(qq, "&&", qq, ":", qq && qq)

print(qq, "||", ww, ":", qq || ww)
print(ww, "||", ww, ":", ww || ww)

print("!",qq, ":", !qq)
print("!",ww, ":", !ww)

 

연산우선순위

여러 연산자를 섞어서 쓰게되면, 우선순위에 따라 연산 순서가 정해진다. 

var height = 195.4
var color = "grey"

print("height >= 185+20 && color == \"red\" : ", height >= 185+20 && color == "red")
print("height >= 185-10 || color == \"red\" : ", height >= 185-10 || color == "red")

산술 > 비교 > 논리 순서로 연산이 이루어진다. 

 

복합할당 연산자

할당(대입)연산과 다른 연산을 한번에 할 수 있도록 결합되어진 연산자다.

a = 8

print("a:", a)
a += 3
print("a += 3:", a )
a -= 3
print("a -= 3:", a )
a *= 3
print("a *= 3:", a )
a /= 3
print("a /= 3:", a )
a %= 3
print("a %= 3:", a )

 

삼항 연산자

조건식 ? A : B

항이 3개이다. 조건식이 참이라면 A를 반환, 거짓이라면 B를 반환한다.

var score = 85
var res = score >= 80 ? "합격" : "불합격"

print(score,":",res)

score가 80이상이라는 조건식을 만족하였으므로 "합격"이 res변수에 대입된 것이다. 

 

casting

형 변환(casting)이란, 서로 다른 자료형과의 연산을 위해, 혹은 변수를 다른 형태로 표현하기 위해 자료형을 변환하는 것을 뜻한다. 보통 자료형(변수) 형태로 사용한다. 

var x = 30
var y = 1.2

var z = x + y   //Binary operator '+' cannot be applied to operands of type 'Int' and 'Double'

서로 다른 자료형은 연산을 할 수 없다는 에러가 표시된다. 

var x = 30
var y = 1.2

var z = Double(x) + y
print("z:",z)

예시와 같이 변수 x를 형변환을 통해 실수형으로 변환하여 두 변수의 연산이 가능해진다.

그렇다면 형변환을 하게 되면 자료는 어떤 식으로 변화가 일어날까?

var x = 30
var y = 1.8

print("Double(x):",Double(x))
print("Int(y):",Int(y))

정수형을 실수형으로 변환 시 큰 문제가 없다. 소수점 .0이 추가될 뿐이다. 하지만 실수형을 정수형으로 변환 시 소수점 이하 자리는 없어지게 된다. 따라서 자료형 변환 시 손실되는 자료가 생기는지 확인이 필요하다.

var h:Int16 = 128
print(Int8(h))

위와 같은 경우도 조심해야 한다. Int16에서는 128을 표현할 수 있지만, Int8의 범위는 127 ~ -128 즉 128은 Int8에는 담을 수 없는 표현 범위의 숫자이다. 형 변환을 시도할 때에는 이러한 여러가지 문제점이 발생 할 수 있다는 점을 알아두자.

'iOS > TJ' 카테고리의 다른 글

day06_control flow_loop  (0) 2021.05.27
day05_control flow_loop  (0) 2021.05.25
day04_control flow_conditional  (0) 2021.05.22
day02_var  (0) 2021.05.18
day01_print()  (0) 2021.05.13

+ Recent posts