07/09/2018, 17:09

RxSwift: Bài 5 - Observables and Subjects in Practice (Part 2)

RxSwift: Bài 5 - Observables and Subjects in Practice (Part 2) Step 3: Talking to other view controllers via subjects Phần này ta sẽ connect ViewController chính của ta với PhotosViewController, để người dùng có thể chọn ảnh tuỳ ý từ album ảnh của họ. Trước hết, ta comment phần hard-code ...

RxSwift: Bài 5 - Observables and Subjects in Practice (Part 2)

Step 3: Talking to other view controllers via subjects
Phần này ta sẽ connect ViewController chính của ta với PhotosViewController, để người dùng có thể chọn ảnh tuỳ ý từ album ảnh của họ.

Trước hết, ta comment phần hard-code h1.png đi, sau đó push cái PhotosViewController vào stack, khi bấm nút + sẽ chuyển qua bên PhotosViewController.

Nếu bạn sử dụng một cái app sử dụng pattern Cocoa, bước tiếp theo bạn sẽ dùng delegate protocol để Photo Controller có thể nói chuyện ngược lại với Main Controller (hay còn gọi là non-reactive way):
alt text

Tuy nhiên trong RxSwift, bạn vẫn có 1 cách thông dụng để giao tiếp giữa hai classes. Đó là thông qua Observable. Không cần phải define protocol nào cả, bởi vì Observable có thể chuyển bất kì loại message nào đến 1 hoặc nhiều người quan tâm đến nó - observers

Step 4: Creating an observable out of the selected photos (Tạo một observable trong số những selected photo)
Add 1 subject vào PhotoVC mà emit một .next event mỗi lần user taps 1 hình từ Camera Roll. Có thể bạn muốn add 1 PublishSubject ở đây để show ra hình được chọn (tức là PublishSubject sẽ vừa nhận vừa phát). Tuy nhiên, không nhất thiết phải để public, vì nó sẽ cho phép những lớp khác gọi onNext (nhập tín hiệu vào) và làm cho subject emit values. Cách này cũng được nhưng mình sẽ làm hướng khác.

Add dòng code sau:
alt text

Mình xin giải thích các dòng code một chút:

  • Biến private PublishSubject sẽ emit những hình được chọn
  • Biến public selectedPhotos sẽ show ra cái observable của Subject
  • Subscribing cái property này là cách mà ViewController có thể quan sát dòng photo sequence mà không cần phải can thiệp vào nó.

PhotosViewController đã chứa đoạn code để đọc photo từ Camera Roll và hiển thị lên Collection View rồi (trong phần collectionView(_:didSelectItemAt:)). Tất cả những gì bạn cần làm là add code để phát tín hiệu khi user tap lên collection view cell

Tiếp theo, trong phần imageManager.requestImage(...) để lấy photo được chọn và cho bạn chọn hình và các thông số để làm việc với completion closure. Trong closure này, bạn sẽ phát ra tín hiệu .next event từ selectedPhotosSubject, trong đoạn code này, các bạn add:
alt text

Mình giải thích code một chút, sử dụng info dictionary để check liệu hình là thumbnail hay full. Trong event của mình chỉ nhận full-size, nên khi có hình nào available thì bạn add thông tin vào cho nó thông qua onNext(_:) ở cái subject nhận tín hiệu của bạn và cung cấp nó với full photo.

Vậy đó, đây là cách nó phát ra 1 chuỗi observable sequence từ 1 màn hình VC đến VC khác. Không delegate protocol hay closure v..v. Thêm nữa, khi mà đã remove protocols, mối quan hệ giữa các controllers trở nên đơn giản hơn nhiều, các bạn xem hình sau:
alt text

Step5: Observing the sequence of selected photos
Nhiệm vụ tiếp theo của bạn là quay lại ViewController và thêm đoạn code sau để hoàn thành cho xong phần phát-gọi, cụ thể là quan sát sequence của selected photos
Tại actionAdd() and thêm dòng code sau trước khi khi push controller lên trên navigation stack:
alt text
Trước khi bạn push controller, subscribe cái events trên selectedPhotos observable của nó. Có 2 cái mình muốn dùng là .onNext và .onDisposed. Compiler lúc này báo warning mình khai báo self mà chưa dùng, do đó mình thêm đoạn code sau:
alt text

Run app và chạy thôi!
À Mình quên note, để chạy được phần này các bạn phải cấp quyền cho app truy cập vào photo library như sau:
Edit trong phần Info.list cặp key-value sau:

<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>

Đây là thành quả:
alt text

0