[RxSwift] #6 performSegue / Single, Maybe, Completable

12180 단어 swiftiOSrxswiftiOS

raywenderlich RxSwift Ch1~4

raywenderlich 의 RxSwift 책을 기반으로 한 RxSwift 정리 를 보고 공부하고 있다. Ch1 ~ Ch3 의 경우는 앞서 정리했던 곰튀김님의 강의에서 들은 Observable과 Subject를 조금 더 실용적인 예제로 살펴보고 문제도 풀어보는 정도의 내용이었다.



Ch4는 Relay, Subject 를 이용한 이미지 콜라주 어플리케이션 예제였다. UI는 이미 다 작성된 뼈대 위에 RxSwift를 얹어서 Clear, Save, + 버튼에 대한 코드를 작성하는 것이었다. 예제 코드는 여기에!


PhotosViewController (이하 PhotosVC), MainViewController (이하 MainVC)

원래 좋아하는 공부 방식인 코드 순서대로 따라가는 것 정리하기의 경우는 원글에서 너무 잘 해두셨기 때문에, 새로 알게 된 포인트들에 대해서 정리해보려고 한다.


1. VC 이동 시, 데이터 주고 받기

MainVC -> PhotosVC 로 이동하여 PhotosVC 에서 사진을 골라서 MainVC 에 사진 데이터를 넘겨줘야하는 이런 경우에는, 보통 delegate 를 이용해서 넘겨주기 마련이다. PhotosVC 에서는 delegate 를 이용하여 처리를 위임하고 실 처리는 MainVC 의 함수에서 한다.

하지만, Rx에서는 delegate 패턴을 사용하지 않는다.

Observable 로 양쪽 VC에서 데이터의 흐름을 구독하게 할 수 있기 때문이다.

// MainVC
@IBAction func actionAdd() {
  let photosVC = storyboard?.instantiateViewController(withIdentifier: "PhotosViewController") as! PhotosViewController
  navigationController?.pushViewController(photosVC, animated: true)
  
  // 그 대신 이렇게 이동할 VC의 Observable 을 구독하여 데이터를 받아온다.
  photosVC.selectedPhotos
    .subscribe(onNext: { [weak self] image in
      guard let images = self?.images else { return }
      images.accept(images.value + [image])
    }, onDisposed: {
      print("photo selection completed")
    })
    .disposed(by: disposeBag)
}
// PhotosVC
private var selectedPhotosSubject = PublishSubject<UIImage>()
// MainVC 에서 selectedPhotos에 데이터를 보낼 일이 없기 때문에, 데이터의 수정을 막기 위해 Observable 을 구독하게 한다.
var selectedPhotos: Observable<UIImage> {
  return selectedPhotosSubject.asObservable()
}

대신 여기서 신경써야 하는 부분은, MainVC 에서 selectedPhotos 를 구독하고 있기 때문에, PhotosVC 가 없어진다고 해서 selectedPhotosSubject 가 메모리에서 해제되지 않는다는 점이다.

// PhotosVC
override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
    
  selectedPhotosSubject.onCompleted()
}

viewWillDisappear 에서 명시적으로 Subject를 종료시켜서 해제하자.



2. Single, Maybe, Completable / Custom Observable


Custom Observable 코드를 (photo id 하나만 emit 하는) Single 을 이용해서 refactoring 해보았다.

  static func save(_ image: UIImage) -> Single<String> {
    // return Observable.create({ observer in
    return Single.create (subscribe: { observer in
      var saveAssetId: String?
      PHPhotoLibrary.shared().performChanges({
        
        let request = PHAssetChangeRequest.creationRequestForAsset(from: image)
        saveAssetId = request.placeholderForCreatedAsset?.localIdentifier
      }, completionHandler: { success, error in
        DispatchQueue.main.async {
          if success, let id = saveAssetId {
//            observer.onNext(id)
//            observer.onCompleted()
            observer(.success(id))
          } else {
            observer(.error(error ?? Errors.couldNotSavePhoto))
          }
        }
      })
      return Disposables.create()
    })
  }
}



3. guard let else { return }

RxSwift 에서만 쓰이는 내용은 아니지만, 부분에 불러와야 하는 요소 중 nil 이 될 가능성이 있는 것을 불러와서 사용하면 guard 문 뒤로는 ? ! 를 붙일 필요가 없어서 편하게 사용할 수 있다. 적극 활용해야겠다.



느낀점

잘 모르겠을 때는 프로젝트로 직접 코드를 쳐보는게 최고라는 생각에 그냥 순서대로 쭉 따라서 코드를 한번 치고 최대한 흐름을 기억해보면서 조금씩 치팅하면서 코드를 또 쳐보는 방식으로 공부를 진행했다. 조금이나마 Observable 을 사용해서 데이터를 처리하는 방식을 손에 익힌 것 같다.

어느 상황에서 어떤 것을 써야하는지는 아직 감이 잘 안오지만, 강의 자료 Challenge 에 있는 것처럼 Observable로 만들고 Single로 리팩토링 하는 방식도 좋은 방식이니까!!! 일단 최대한 익숙해지자.

좋은 웹페이지 즐겨찾기