传递数据MVVM和RxSwift

问题描述 投票:1回答:1

我目前正在学习MVVM和RxSwift。我在主视图控制器中有一个要传递的图像。我成功使用了mvc和RxSwift,但由于MVVM对我来说是新的。我不知道如何在MVVM中实现。这是我的代码。

// This is the work version MVC RxSwift
    class GProfilePickAlertVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    private let selectedSubjectPhoto = PublishSubject<UIImage>()
    var selectedPhoto: Observable<UIImage> {
        return selectedSubjectPhoto.asObservable()
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let editedImage     = info[.editedImage] as? UIImage {
            self.selectedSubjectPhoto.onNext(editedImage)
            dismiss(animated: true, completion: nil)
        }
        dismiss(animated: true, completion: nil)
    }
}

    class BasicInfoViewController: UITableViewController {
    let profileImageView    = GProfileImage(img: #imageLiteral(resourceName: "ic-tab-profile"), renderingMode: .alwaysTemplate)

    @objc private func handlePickPhoto() {
        let pickPhotoVC = GProfilePickAlertVC()
        pickPhotoVC.selectedPhoto.subscribe(onNext: { image in
            self.profileImageView.clipsToBounds = true
            self.profileImageView.image = image
            }).disposed(by: disposeBag)
        pickPhotoVC.modalPresentationStyle = .overFullScreen
        pickPhotoVC.modalTransitionStyle = .crossDissolve
        present(pickPhotoVC, animated: true)
    }
}

// This is my MVVM setup
    struct BasicInfoViewModel {

    let selectedImage: BehaviorRelay<UIImage>
}

    class BasicInfoViewController: UITableViewController {

    let disposeBag          = DisposeBag()

    var BasicInfoViewModel: BasicInfoViewModel!
}
mvvm uiimage rx-swift
1个回答
1
投票

这就是我最后得到的。在这种情况下,视图模型实际上没有什么可做的,因为只有一行逻辑。

代码的基本结构与您的MVC示例相同,除了我的代码使用RxImagePickerDelegateProxy而不是GProfilePickAlertVC。前者是一个通用委托,它将根据需要由Rx系统自动附加到任何UIImagePickerController。

imagePickerScene(on:modalPresentationStyle:modalTransitionStyle:)功能负责显示和关闭图像选择器。它充当协调者。

castOrThrow(_:_:)函数是处理转换的通用帮助器。您可以在各处使用它。

final class BasicInfoViewController: UIViewController {

    private let profileImageView = GProfileImage(img: #imageLiteral(resourceName: "ic-tab-profile"), renderingMode: .alwaysTemplate)
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let imagePicker = imagePickerScene(
            on: self, 
            modalPresentationStyle: .overFullScreen, 
            modalTransitionStyle: .crossDissolve
        )

        pickPhotoButton.rx.tap
            .flatMapLatest { Observable.create(imagePicker) }
            .compactMap { $0[.editedImage] as? UIImage }
            .bind { image in
                self.profileImageView.clipsToBounds = true
                self.profileImageView.image = image
            }
            .disposed(by: disposeBag)
    }
}

func imagePickerScene(on presenter: UIViewController, modalPresentationStyle: UIModalPresentationStyle? = nil, modalTransitionStyle: UIModalTransitionStyle? = nil) -> (_ observer: AnyObserver<[UIImagePickerController.InfoKey: AnyObject]>) -> Disposable {
    return { [weak presenter] observer in
        let controller = UIImagePickerController()
        if let presentationStyle = modalPresentationStyle {
            controller.modalPresentationStyle = presentationStyle
        }
        if let transitionStyle = modalTransitionStyle {
            controller.modalTransitionStyle = transitionStyle
        }
        presenter?.present(controller, animated: true)
        return controller.rx.didFinishPickingMediaWithInfo
            .do(onNext: { _ in
                presenter?.dismiss(animated: true)
            })
            .subscribe(observer)
    }
}

final class RxImagePickerDelegateProxy: DelegateProxy<UIImagePickerController, UINavigationControllerDelegate & UIImagePickerControllerDelegate>, DelegateProxyType, UINavigationControllerDelegate & UIImagePickerControllerDelegate {

    static func currentDelegate(for object: UIImagePickerController) -> (UIImagePickerControllerDelegate & UINavigationControllerDelegate)? {
        return object.delegate
    }

    static func setCurrentDelegate(_ delegate: (UIImagePickerControllerDelegate & UINavigationControllerDelegate)?, to object: UIImagePickerController) {
        object.delegate = delegate
    }

    static func registerKnownImplementations() {
        self.register { RxImagePickerDelegateProxy(parentObject: $0, delegateProxy: RxImagePickerDelegateProxy.self) }
     }
}

extension Reactive where Base: UIImagePickerController {

    var didFinishPickingMediaWithInfo: Observable<[UIImagePickerController.InfoKey: AnyObject]> {
        return RxImagePickerDelegateProxy.proxy(for: base)
            .methodInvoked(#selector(UIImagePickerControllerDelegate.imagePickerController(_:didFinishPickingMediaWithInfo:)))
            .map({ (a) in
                return try castOrThrow(Dictionary<UIImagePickerController.InfoKey, AnyObject>.self, a[1])
            })
    }
}

func castOrThrow<T>(_ resultType: T.Type, _ object: Any) throws -> T {
    guard let returnValue = object as? T else {
        throw RxCocoaError.castingError(object: object, targetType: resultType)
    }

    return returnValue
}
© www.soinside.com 2019 - 2024. All rights reserved.