Swift Language
RxSwift
수색…
RxSwift 기본 사항
FRP 또는 Functional Reactive Programming에는 알아야 할 몇 가지 기본 용어가 있습니다.
모든 데이터 조각은 Observable
비동기 데이터 스트림)으로 표현 될 수 있습니다. FRP의 힘은 스트림과 같이 동기식 및 비동기식 이벤트를 표현하고 Observable
하며 동일한 인터페이스를 제공하여 작업합니다.
일반적으로 Observable
은 날짜 -. .Next
이벤트를 보유하는 여러 이벤트 (또는 없음)를 보유하고 성공적으로 종료 ( .Success
)하거나 오류 ( .Error
)로 종료 될 수 있습니다.
다음 대리석 다이어그램을 살펴 보겠습니다.
--(1)--(2)--(3)|-->
이 예제에는 Int
값의 스트림이 있습니다. 시간이 진행되면서 3 개의. .Next
이벤트가 발생하고 스트림이 성공적으로 종료되었습니다.
--X->
위의 다이어그램은 데이터가 방출되지 않았으며 .Error
이벤트가 Observable
종료 한 경우를 보여줍니다.
계속하기 전에 유용한 자료가 있습니다.
- RxSwift . 예제를보고, 문서를 읽고 시작하십시오.
- RxSwift Slack room 에는 교육 문제 해결을위한 몇 가지 채널이 있습니다.
- RxMarbles 를 사용하여 어떤 작업자가 어떤 작업 을하는지, 어떤 작업이 가장 유용한 지 알아보십시오.
- 이 예제 를 살펴보고 직접 코드를 탐색하십시오.
관찰 대상 만들기
RxSwift 는 Observable
을 만드는 다양한 방법을 제공합니다.
import RxSwift
let intObservale = Observable.just(123) // Observable<Int>
let stringObservale = Observable.just("RxSwift") // Observable<String>
let doubleObservale = Observable.just(3.14) // Observable<Double>
그래서 관측치가 생성됩니다. 그들은 하나의 가치를 지니고 성공으로 끝납니다. 그럼에도 불구하고 그것이 창조 된 후에는 아무 일도 일어나지 않습니다. 왜?
Observable
을 사용하여 작업하는 두 단계가 있습니다 . 스트림을 생성 하기 위해 뭔가를 관찰 한 다음 스트림을 구독 하거나 스트림을 상호 작용 하기 위해 바인딩 합니다.
Observable.just(12).subscribe {
print($0)
}
콘솔에서 다음을 인쇄합니다.
.Next(12)
.Completed()
그리고 .Next
이벤트에서 발생하는 데이터 작업에만 관심이 있다면 subscribeNext
연산자를 사용합니다.
Observable.just(12).subscribeNext {
print($0) // prints "12" now
}
많은 값을 관찰 할 수있게 만들려면 다른 연산자를 사용합니다.
Observable.of(1,2,3,4,5).subscribeNext {
print($0)
}
// 1
// 2
// 3
// 4
// 5
// I can represent existing data types as Observables also:
[1,2,3,4,5].asObservable().subscribeNext {
print($0)
}
// result is the same as before.
그리고 마침내, Observable
을 원하고 아마도 약간의 일을하고 싶습니다. 예를 들어 Observable<SomeResultType>
네트워크 작업을 래핑하는 것이 편리합니다. 우리가 이것을 달성 할 수 있는지 살펴 보겠습니다.
Observable.create { observer in // create an Observable ...
MyNetworkService.doSomeWorkWithCompletion { (result, error) in
if let e = error {
observer.onError(e) // ..that either holds an error
} else {
observer.onNext(result) // ..or emits the data
observer.onCompleted() // ..and terminates successfully.
}
}
return NopDisposable.instance // here you can manually free any resources
//in case if this observable is being disposed.
}
처분
가입이 생성 된 후 올바른 할당 해제를 관리하는 것이 중요합니다.
문서에서
시퀀스가 유한 한 시간에 종료되면, dispose를 호출하지 않거나 addDisposableTo (disposeBag)를 사용하지 않으면 영구적 인 리소스 누출이 발생하지 않습니다. 그러나 요소 생성을 완료하거나 오류를 반환하여 시퀀스가 완료 될 때까지 해당 자원이 사용됩니다.
리소스를 할당 해제하는 두 가지 방법이 있습니다.
-
disposeBag
및addDisposableTo
연산자 사용. -
takeUntil
연산자 사용.
첫 번째 경우에는 수동으로 DisposeBag
개체에 구독을 전달합니다.이 개체는 촬영 된 모든 메모리를 올바르게 지 웁니다.
let bag = DisposeBag()
Observable.just(1).subscribeNext {
print($0)
}.addDisposableTo(bag)
내가 DisposeBag
모든 클래스에 DisposeBag
를 실제로 생성 할 필요는 없습니다. NSObject + Rx 라는 RxSwift 커뮤니티 의 프로젝트를 살펴보십시오. 프레임 워크를 사용하면 위의 코드를 다음과 같이 다시 작성할 수 있습니다.
Observable.just(1).subscribeNext {
print($0)
}.addDisposableTo(rx_disposeBag)
두 번째 경우에 구독 시간이 self
개체 수명과 일치하면 takeUntil(rx_deallocated)
사용하여 takeUntil(rx_deallocated)
를 구현할 수 있습니다.
let _ = sequence
.takeUntil(rx_deallocated)
.subscribe {
print($0)
}
바인딩
Observable.combineLatest(firstName.rx_text, lastName.rx_text) { $0 + " " + $1 }
.map { "Greetings, \($0)" }
.bindTo(greetingLabel.rx_text)
두 Observables
중 하나가 항목을 combineLatest
때마다 combineLatest
연산자를 사용하여 각 Observable
방출하는 최신 항목을 결합합니다. 그래서이 방법으로 두 개의 UITextField
결과를 새로운 메시지를 만들어 "Greetings, \($0)"
문자열 결합을 사용하여 나중에 UILabel
의 텍스트에 바인딩합니다.
매우 쉬운 방법으로 모든 UITableView
및 UICollectionView
에 데이터를 바인딩 할 수 있습니다.
viewModel
.rows
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
cell.title = viewModel.title
cell.url = viewModel.url
}
.addDisposableTo(disposeBag)
이것은 cellForRowAtIndexPath
데이터 소스 메소드를 둘러싼 Rx 래퍼입니다. 또한 Rx는 전통적인 의미에서 필수적인 메소드 인 numberOfRowsAtIndexPath
의 구현을 처리하지만 여기서는 구현하지 않아도됩니다.
RxCocoa 및 ControlEvents
RxSwift는 데이터를 제어하는 방법뿐 아니라 반응적인 방식으로 사용자 작업을 표현하는 방법도 제공합니다.
RxCocoa에는 필요한 모든 것이 들어 있습니다. UI 구성 요소의 대부분의 속성을 Observable
랩핑하지만 실제는 그렇지 않습니다. ControlEvent
(이벤트를 나타냄) 및 ControlProperties
(놀랍게도 속성을 나타내는!)라는 업그레이드 된 Observable
이 있습니다. 이러한 것들은 Observable
스트림을 저장하지만 몇 가지 뉘앙스가 있습니다.
- 결코 실패하지 않으므로 오류가 발생하지 않습니다.
- 할당 해제되는 컨트롤의 시퀀스를
Complete
합니다. - 메인 스레드 (
MainScheduler.instance
)에서 이벤트를 전달합니다.
기본적으로 다음과 같이 평소와 같이 작업 할 수 있습니다.
button.rx_tap.subscribeNext { _ in // control event
print("User tapped the button!")
}.addDisposableTo(bag)
textField.rx_text.subscribeNext { text in // control property
print("The textfield contains: \(text)")
}.addDisposableTo(bag)
// notice that ControlProperty generates .Next event on subscription
// In this case, the log will display
// "The textfield contains: "
// at the very start of the app.
이것은 사용하는 것이 매우 중요합니다 : 당신이 Rx를 사용하는 한 @IBAction
물건에 대해 잊어 버려야합니다. 필요한 모든 것을 바인딩하고 한 번에 구성 할 수 있습니다. 예를 들어,보기 컨트롤러의 viewDidLoad
메서드는 UI 구성 요소의 작동 방식을 설명하는 좋은 후보입니다.
다른 예제 : 텍스트 필드, 버튼 및 레이블이 있다고 가정합니다. 우리는 버튼을 누를 때 텍스트 필드의 텍스트 를 검증 하고 그 결과를 레이블에 표시 하려고합니다. 네, 또 다른 검증 이메일 작업 같아 보입니까?
우선, 우리는 버튼을 잡아. button.rx_tap
ControlEvent :
----()-----------------------()----->
여기 빈 괄호는 사용자 탭을 보여줍니다. 다음으로 우리는 withLatestFrom
연산자를 사용하여 textField에 작성된 것을 취합니다 ( 여기서는 상위 스트림이 사용자 탭을 나타내며 아래쪽이 텍스트 필드의 텍스트를 나타냄).
button.rx_tap.withLatestFrom(textField.rx_text)
----("")--------------------("123")--->
// ^ tap ^ i wrote 123 ^ tap
좋았어, 유효성을 검사 할 때만 출력되는 유효성을 검사 할 문자열이 있습니다.
Observable
에는 map
또는 filter
와 같은 친숙한 연산자가 있으므로 map
를 확인하여 텍스트의 유효성을 검사합니다. validateEmail
함수를 직접 작성하고 원하는 정규 표현식을 사용하십시오.
button.rx_tap // ControlEvent<Void>
.withLatestFrom(textField.rx_text) // Observable<String>
.map(validateEmail) // Observable<Bool>
.map { (isCorrect) in
return isCorrect ? "Email is correct" : "Input the correct one, please"
} // Observable<String>
.bindTo(label.rx_text)
.addDisposableTo(bag)
끝난! 더 많은 커스텀 로직이 필요하다면 (오류 발생시 오류보기를 보여주고, 성공하면 다른 화면으로 전환하는 등) 최종 Bool
스트림을 구독하고 거기에 쓰면됩니다.