murawakimitsuhiro
8/24/2018 - 5:29 AM

RxSwiftを使い、UIImagePickerControllerをラップしたクラス。

RxSwiftを使い、UIImagePickerControllerをラップしたクラス。

import Foundation
import UIKit
import Photos

import RxSwift
import RxCocoa

final class RxImagePicker: NSObject {
    
    private let didFinishPickingMediaSubject: PublishSubject<UIImage> = PublishSubject<UIImage>()
    private let didCancelSubject: PublishSubject<Void> = PublishSubject<Void>()
    
    public var didFinishPickingMedia: Observable<UIImage> { return didFinishPickingMediaSubject.asObserver() }
    public var didCancel: Observable<Void> { return didCancelSubject.asObserver() }

    public func selectImage(viewController fromViewController: UIViewController, tintColor: UIColor? = nil, allowEditing: Bool = false) {
        checkPermission()
        
        let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        let cameraAction = UIAlertAction(title: "写真を撮る", style: .default) { (UIAlertAction) -> Void in
            self.selectFromCamera(fromViewController: fromViewController, allowEditing: allowEditing)
        }
        
        let libraryAction = UIAlertAction(title: "アルバムから選ぶ", style: .default) { (UIAlertAction) -> Void in
            self.selectFromLibrary(fromViewController: fromViewController, allowEditing: allowEditing)
        }
        
        let cancelAction = UIAlertAction(title: "キャンセル", style: .cancel) { (UIAlertAction) -> Void in
            fromViewController.dismiss(animated: true, completion: nil)
        }
        
        alertController.view.tintColor = tintColor
        alertController.addAction(cameraAction)
        alertController.addAction(libraryAction)
        alertController.addAction(cancelAction)
        fromViewController.present(alertController, animated: true, completion: nil)
    }
    
    func checkPermission() {
        let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
        switch photoAuthorizationStatus {
        case .authorized:
            print("Access is granted by user")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization({
                (newStatus) in
                print("status is \(newStatus)")
                if newStatus ==  PHAuthorizationStatus.authorized {
                    /* do stuff here */
                    print("success")
                }
            })
            print("It is not determined until now")
        case .restricted:
            // same same
            print("User do not have access to photo album.")
        case .denied:
            // same same
            print("User has denied the permission.")
        }
    }
    
    private func selectFromCamera(fromViewController: UIViewController, allowEditing: Bool) {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            let imagePickerController = UIImagePickerController()
            imagePickerController.delegate = self
            imagePickerController.sourceType = UIImagePickerControllerSourceType.camera
            imagePickerController.allowsEditing = allowEditing
            fromViewController.present(imagePickerController, animated: true, completion: nil)
        } else {
            print("カメラ許可をしていない時の処理")
        }
    }
    
    private func selectFromLibrary(fromViewController: UIViewController, allowEditing: Bool) {
        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
            let imagePickerController = UIImagePickerController()
            imagePickerController.delegate = self
            imagePickerController.sourceType = UIImagePickerControllerSourceType.photoLibrary
            imagePickerController.allowsEditing = allowEditing
            fromViewController.present(imagePickerController, animated: true, completion: nil)
        } else {
            print("カメラロール許可をしていない時の処理")
        }
    }
}

extension RxImagePicker: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        didCancelSubject.onNext(())
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
            didFinishPickingMediaSubject.onNext(image)
        }
        
        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
           didFinishPickingMediaSubject.onNext(image)
        }
        
        picker.dismiss(animated: true, completion: nil)
    }
}