All Projects → blkbrds → Rxswift Tutorials

blkbrds / Rxswift Tutorials

Reactive Programming with Swift

Programming Languages

swift
15916 projects

Labels

Projects that are alternatives of or similar to Rxswift Tutorials

Rxswift
Reactive Programming in Swift
Stars: ✭ 21,163 (+58686.11%)
Mutual labels:  rxswift
Artify Core
The sweet heart of Artify 👑
Stars: ✭ 17 (-52.78%)
Mutual labels:  rxswift
Slidestock
Viewer app for slides provided by speaker deck.
Stars: ✭ 10 (-72.22%)
Mutual labels:  rxswift
Drrrible
Dribbble for iOS using ReactorKit
Stars: ✭ 487 (+1252.78%)
Mutual labels:  rxswift
Rxautomaton
🤖 RxSwift + State Machine, inspired by Redux and Elm.
Stars: ✭ 711 (+1875%)
Mutual labels:  rxswift
Swiftstudy
Swift 스터디 자료집
Stars: ✭ 23 (-36.11%)
Mutual labels:  rxswift
Xrouter
Navigate anywhere in just one line.
Stars: ✭ 411 (+1041.67%)
Mutual labels:  rxswift
Videoplayer
AVPlayer control and monitoring made easy (with Rx)
Stars: ✭ 29 (-19.44%)
Mutual labels:  rxswift
Rxcombine
Bi-directional type bridging between RxSwift and Apple's Combine framework
Stars: ✭ 741 (+1958.33%)
Mutual labels:  rxswift
Rxdatasources Texture
ASTable and ASCollection Data Sources for RxSwift (Texture)
Stars: ✭ 25 (-30.56%)
Mutual labels:  rxswift
Iossampleapp
Sample iOS app demonstrating Coordinators, Dependency Injection, MVVM, Binding
Stars: ✭ 510 (+1316.67%)
Mutual labels:  rxswift
Awesome Swift Korean Lecture
훌륭한 Swift 세션 동영상(강좌), 한글 자막있는 혹은 한국어 강의 정보 링크 모음 (Awesome Swift Korean lecture information)
Stars: ✭ 649 (+1702.78%)
Mutual labels:  rxswift
Rxfeedback.swift
The universal system operator and architecture for RxSwift
Stars: ✭ 928 (+2477.78%)
Mutual labels:  rxswift
Coordinator Mvvm Rx Example
Example of MVVM-C architecture implemented with RxSwift
Stars: ✭ 469 (+1202.78%)
Mutual labels:  rxswift
Iosdc2017
iOSDC2017発表資料
Stars: ✭ 13 (-63.89%)
Mutual labels:  rxswift
Veditorkit
Lightweight and Powerful Editor Kit
Stars: ✭ 441 (+1125%)
Mutual labels:  rxswift
Ios Architecture
A collection of iOS architectures - MVC, MVVM, MVVM+RxSwift, VIPER, RIBs and many others
Stars: ✭ 901 (+2402.78%)
Mutual labels:  rxswift
Evreflection
Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift
Stars: ✭ 954 (+2550%)
Mutual labels:  rxswift
Flags
🇸🇪 Flag extension make flag emoji, image
Stars: ✭ 28 (-22.22%)
Mutual labels:  rxswift
Rxswiftexamples
Examples and resources for RxSwift.
Stars: ✭ 930 (+2483.33%)
Mutual labels:  rxswift

Reactive Programming with Swift

Mọi chia sẻ hay sao chép phải được cấp phép, tác quyền thuộc team iOS - Asian Tech, Inc

Contents

  1. Get Started

    1. Reactive
    2. Observable và Observer
    3. Operator - man in the middle
    4. Subjects
  2. Deep Dive

    1. Creation
    2. Operators
    3. MVVM
  3. Advanced(Update later)

  4. Testing

    1. RxTests
    2. RxNimble(Update later)

1. Getting Started

1.1. Reactive

Reactive programming là gì?

  • Reactive programming is programming with asynchronous data streams.

    Reactive programming là phương pháp lập trình với luồng dữ liệu bất đồng bộ hay những thay đổi có tính lan truyền (the propagation of change). Khái niệm luồng (stream) rất phổ biến, bạn có thể tạo một luồng từ bất kì kiểu dữ liệu nào: các biến (variables), giá trị đầu vào từ người dùng (user inputs), properties, caches, data structures, etc. Có thể nói luồng là trung tâm của reactive.

  • Một luồng là một dãy(sequence) các sự kiện đang diễn ra được sắp xếp theo thời gian. Nó có thể phát ra 3 thứ: một value, một error, hoặc một completed.

  • Để minh họa cho luồng người ta hay dùng một loại biểu đồ gọi là marble diagram, loại diagram này rất đơn giản, trực quan và dễ hiểu. Mô hình dưới đây là luồng sự kiện "click vào 1 button"

reactive

  • Ở đây tín hiệu giúp ta biết được khi nào luồng sự kiện click completed là khi window hoặc view chứa button bị đóng lại.
  • Chúng ta bắt các sự kiện bất đồng bộ (ví dụ như tap vào button, gọi API, ...) bằng cách define một function dùng để xử lý một giá trị được phát ra, một function khác để handle error, tương tự với completed. Các function chúng ta define là các observer, luồng là chủ thể đang được lắng nghe hay còn gọi là Observable. Ví dụ sử dụng mã ASCII để minh hoạ:
--a---b-c---d---X---|->

a, b, c, d là các giá tr được phát ra
X là mt 'error' nào đó
| là mt signal 'completed'

Ta có thể xem đây là một stream

1.2. Observable và Observer

1.2.1 Mở đầu

  • Có rất nhiều thuật ngữ dùng để mô tả và thiết kế của lập trình bất đồng bộ. Trong tài liệu này sẽ chỉ sử dụng thuật ngữ ObserverObservable.

1.2.2 Observer và Observable là gì?

  • Observer lắng nghe Observable.
  • Observable phát ra các items hoặc gửi các notifications đến các Observer bằng cách gọi các Observer methods.

Khái niệm Observable đến từ observer design pattern là một đối tượng thông báo cho các đối tượng theo dõi về một điều gì đó đang diễn ra. source

  • Diagram dưới đây biểu diễn Observable và quá trình biến đổi của nó:

Observable-diagram

  • Một Observer đăng ký lắng nghe một Observable, sau đó nó sẽ xử lý một item hoặc nhiều các item mà Observable phát ra.

1.2.2 Khởi tạo Observable và Observer

  • Về cơ bản flow của việc khởi tạo đều trải qua các bước sau:

    • Khai báo một method có giá trị được trả về từ một hàm gọi bất đồng bộ, method này là một phần của Observer.
    • Khai báo một Observable.
    • Đăng kí Observer vào Observable.
    • Method của Observer sẽ bắt đầu xử lý các business logic dựa trên giá trị trả về hoặc các giá trị được phát ra bởi Observerble.
    // Khai báo một observer
    def myOnNext = { value -> x lý các business logic vi value }
    // Khai báo một Observable
    def myObservable = someObservable(itsParameters);
    // Đăng ký observer vào observable
    myObservable.subscribe(myOnNext);
    
  • onNext, onCompleted, và onErrror

    Subscribe method là cách kết nối Observer với Observable. Observer's implementation gồm các method:

    onNext: Observable gọi hàm onNext có tham số là item, item này là một trong các tập items của Observable

    onError: Được gọi khi Observable kết thúc với một lỗi xảy ra trong quá trình chuyển đổi, xử lý dữ liệu.

    onCompleted: Observable gọi hàm này sau khi hàm onNext cuối cùng được gọi, nếu không có bất kì lỗi nào xảy ra.

    Ví dụ bằng code swift:

    let obj = Observable.from(["🐶", "🐱", "🐭", "🐹"]) // Khởi tạo một Observable
    obj.subscribe( // Thực hiện subscribe Observable
      onNext: { data in
        print(data) // Nơi nhận dữ liệu của Observer được gửi đi từ Observable
      }, 
      onError: { error in
        print(error) // Nơi nhận error và Observable được giải phóng
      }, 
      onCompleted: {
        print("Completed") // Nhận được sự kiện khi Observable hoàn thành và Observable được giải phóng
      })
       .disposed()
    
    🐶
    🐱
    🐭
    🐹
    Completed
    

    iOS

    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
      super.viewDidLoad()
      let observable = textField.rx.text.orEmpty // Khởi tạo observable
      observable.subscribe(onNext: { (text) in 
      // Mỗi lần thay đổi text trong textField, Observer sẽ nhận được giá trị text mới của textField.
        print(text)
      })
    }
    

  • "Hot" và "Cold" Observable

    Khi nào Observable phát ra chuỗi các items? Điều đó phụ thuộc vào Observable. Một "Hot Observable" có thể bắt đầu phát các items ngay khi nó được tạo ra, và sau đó bất kỳ Observer nào đăng ký tới Observable đều có thể bắt đầu quan sát(observing) từ khoảng giữa của tiến trình. Trái lại, "Cold Observable" thì chờ cho đến khi một Observer nào đó đăng kí vào Observable trước khi nó bắt đầu phát ra các items, và do đó Observer có thể đảm bảo được việc quan sát từ toàn bộ tiến trình từ lúc bắt đầu ( to see the whole sequence from the beginning.) Chi tiết

1.3. Operator - man in the middle

Operators là những phép toán cho phép biển đổi observable thành observable mới để phù hợp với nhu cầu sử dụng, chúng ta có thể tạo ra một chuỗi các phép toán để biến đổi observable

Phân loại các operators trong RxSwift:

  • Creating Observables: Gồm các phép toán dùng để khởi tạo observable.
  • Transforming Observables: Gồm các phép toán dùng để biến đổi các giá trị được phát ra bởi observable.
  • Filtering Observables: Gồm các phép toán dùng để chọn lọc các giá trị được phát ra bởi observable.
  • Combining Observables: Gồm các phép toán dùng để nhóm nhiều observables lại thành một observable.
  • Error Handling Operators: Gồm các phép toán dùng để thông báo lỗi từ observable.
  • Observable Utility Operators: Gồm các ultility hữu ích.
  • Conditional and Boolean Operators: Gồm các phép toán điều kiện.
  • Mathematical and Aggregate Operators: Gồm các phép toán tính toán số lượng các giá trị được phát ra.
  • Connectable Observable Operators: Gồm các phép toán có khả năng connect được observable.
  • Operators to Convert Observables: Gồm các phép toán dùng để convert observable thành object hoặc data structure.
Chi tiết từng loại sẽ được trình bày ở đây

Example 1:

Filter

let observable = Observable.of(2,30,22,5,60,1) // 1
let newObservable = observable.filter { $0 > 10 } // 2

OUTPUT: 30 22 60

  1. Khởi tạo observable các số nguyên --2--30--22--5--60--1
  2. Qua phép filter với điều kiện ($0 > 10). Chúng ta đã có được một observable mới là --30--22--60

Example 2: Ở ví dụ này chúng ta sử dụng phép filter vào việc tìm kiếm bằng UISearchBar control

let observable = searchBar.rx.text.orEmpty.asObservable() // 1   

observable.filter { $0.hasPrefix("Number") } // 2
.subscribe(onNext: { (text) in // 3
	// Do something when emit events
})
.disposed(by: disposeBag) // dispose it on deinit.
  1. Khởi tạo observable thể hiện cho sự thay đổi nội dung của search bar
  2. Lọc nội dụng bắt đầu bằng chuỗi Number
  3. Subcrible một observable để có thể xử lý mỗi khi nội dung search bar thay đổi

1.4. Subjects

Một đối tượng vừa có thể là Observable vừa có thể là Observer được gọi là Subject.

​Chẳng hạn khi sử dụng UIImagePickerController, ngoài việc quan tâm tới việc load hình ảnh từ Photos Library (lúc này UIImagePickerController là Observer) thì ứng dụng cần tương tác với chính UIImagePickerController để ẩn, hiển, chọn ảnh… (lúc này UIImagePickerController là Observable). Vậy ta có thể hiểu UIImagePickerController là một Subject ​

1.4.1. PublishSubject

​ PublishSubject là các phần tử có thể được phát ngay sau khi Subject được khởi tạo, bất chấp chưa có đối tượng nào subscribe tới nó (hot observable). Observer sẽ không nhận được các phần tử phát ra trước thời điểm subscribe.

PublishSubject-diagram

// Khởi tạo đối tượng PublishSubject.
let subject = PublishSubject<String>()

// subject phát đi event.
subject.onNext("Is anyone listening?")

// subscriptionOne đăng ký lắng nge đối tượng subject trên.
let subscriptionOne = subject.subscribe(onNext: { string in
	print("1)", string)
})

subject.onNext("1")
subject.onNext("2")

// subscriptionTwo đăng ký lắng nge đối tượng subject trên.
let subscriptionTwo = subject.subscribe { event in
	print("2)", event.element ?? event)
}

subject.onNext("3")

// deinit subscriptionOne
subscriptionOne.dispose()

subject.onNext("4")

// deinit subscriptionTwo
subscriptionTwo.dispose()
// Ouput:
1) 1
1) 2
1) 3
2) 3
2) 4

1.4.2. BehaviorSubject

​ BehaviorSubject có cơ chế hoạt động gần giống với PublishSubject, nhưng Observer sẽ nhận được giá trị mặc định hoặc giá trị ngay trước thời điểm subscribe. Observer sẽ nhận được ít nhất một giá trị.

​ Chẳng hạn, nếu coi việc cuộn thanh trượt của UIScrollView là một observable (offset là giá trị của các phần tử trong stream), thì ngay khi subscribe vào observable, chúng ta cần biết vị trí offset hiện tại của UIScrollView, do vậy chúng ta cần sử dụng BehaviorSubject

BehaviorSubject-diagram

let disposeBag = DisposeBag()

// Khởi tạo đối tượng BehaviorSubject.
let subject = BehaviorSubject(value: "Initial value")

// subject phát đi event.
subject.onNext("1")

// Đăng ký lắng nge đối tượng subject trên.
subject.subscribe {
		print("1)", $0)
	}
	.disposed(by: disposeBag)

subject.onNext("2")

// Đăng ký lắng nge đối tượng subject trên.
subject.subscribe {
		print("2)", $0)
	}
	.disposed(by: disposeBag)

subject.onNext("3")
// Output:
1) 1
1) 2
2) 2
1) 3
2) 3

1.4.3. ReplaySubject

​ ReplaySubject tương tự như BehaviorSubject nhưng thay vì phát thêm duy nhất một phần tử trước đó, ReplaySubject cho phép ta chỉ định số lượng phần tử tối đa được phát lại khi subscribe. Ngoài ra, khi khởi tạo ReplaySubject, chúng ta không cần khai báo giá trị mặc định như BehaviorSubject.

ReplaySubject-diagram

let disposeBag = DisposeBag()

// Khởi tạo đối tượng BehaviorSubject.
let subject = ReplaySubject<String>.create(bufferSize: 2)

// subject phát đi event.
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")

// Đăng ký lắng nge đối tượng subject trên.
subject.subscribe {
		print("1)", $0)
	}
	.disposed(by: disposeBag)

// Đăng ký lắng nge đối tượng subject trên.
subject.subscribe {
		print("2)", $0) 
	}
	.disposed(by: disposeBag)

subject.onNext("4")

// deinit subject
subject.dispose()
// Ouput:
1) 2
1) 3
2) 2
2) 3
1) 4
2) 4

1.4.4. Variable

Variable là một kiểu của BehaviorSubject mà có thể lưu giữ giá trị(Value) hiện tại như một trạng thái(state). Chúng ta có thể truy cập vào giá trị hiện tại đó thông qua thuộc tính value, việc thay đổi value này tương đương với hàm onNext của các loại subject khác

  • Không thể add sự kiện error vào một Variable
  • Không thể add sự kiện completed vào một Variable, sự kiện này chỉ được phát ra khi nó bị deallocated

Chúng ta rất hay dùng subject kiểu Variable, đặc biệt là trong các trường hợp không cần quan tâm tới việc khi nào có error và khi nào completed

let disposeBag = DisposeBag()

// Khởi tạo đối tượng BehaviorSubject.
let variable = Variable("Initial value")

// subject phát đi event.
variable.value = "New initial value"

// Đăng ký lắng nge đối tượng subject trên.
variable.asObservable()
		.subscribe {
			print("1)", $0)
		}
		.disposed(by: disposeBag)

variable.value = "1"

// Đăng ký lắng nge đối tượng subject trên.
variable.asObservable()
		.subscribe {
			print("2)", $0)
		}
		.disposed(by: disposeBag)

variable.value = "2"
1) next(New initial value)
1) next(1)
2) next(1)
1) next(2)
2) next(2)

2. Deep Dive

Sau khi tìm hiểu các khái niệm cơ bản của Reactive programming và RxSwift thì trong phần này, chúng ta sẽ đi sâu hơn vào cách hoạt động, xử lý và ứng dụng trong từng trường hợp cụ thể của chúng.

Creation

Operators

MVVM

3. Advanced(Update later)

4. Testing

Phần này sẽ tập trung vào implement Unit-Testing bằng các framework trên RxSwift Community như RxTests, RxBlocking, RxNimble

4.1. RxTests

4.2. RxNimble (Update later)

References

https://github.com/ReactiveX/RxSwift

http://rxmarbles.com/

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].