美文网首页
RxSwift + MVVM实现仿朋友圈分享视频裁剪功能

RxSwift + MVVM实现仿朋友圈分享视频裁剪功能

作者: unravelW | 来源:发表于2020-03-22 16:18 被阅读0次

最近在学习RxSwift框架实现函数响应式编程,该框架又可以用来写MVVM结构的项目,于是结合这两方面写了一段仿朋友圈视频裁剪功能的代码。

RxSwift框架主要为我们解决的问题是将项目中的点击事件,代理,闭包回调,通知等编程方式统统用RxSwift框架提供的API代替,以统一项目整体的代码风格。

RxSwift框架主要提供以下操作方式

它是通过构建函数操作数据序列,然后对这些序列做出响应的编程方式。

RxSwift在MVVM架构中的应用

MVVM与MVC架构十分相似,它将MVC中controller层中的逻辑代码抽离出来放入viewModel层来轻量化controller中的代码,controller中只负责数据绑定。RxSwift主要负责viewModel中可观察对象和观察者的生成以及controller中这两者之间的绑定关系。

以下为MVVM中各层作用:

Model 数据层,读写数据,保存 App 状态

View 页面层,提供用户输入行为,并且显示输出状态

ViewModel 逻辑层,它将用户输入行为,转换成输出状态

ViewController 主要负责数据绑定

以项目中的代码举例:

controller中做数据绑定的代码

      cropVideoVM = CropVideoViewModel.init(cropVideoVC: self)

        /*Observable bind with Observer*/

        backBtn.rx.tap.bind(to: cropVideoVM.backBtnTapObserver).disposed(by: disposeBag)

        cropVideoVM.editStatePublishSubject.bind(to: cropVideoVM.editStateObserver).disposed(by: disposeBag)

        //preEditState events bind

        view.rx.tapGesture().bind(to: cropVideoVM.rootViewTapGestureObserver).disposed(by: disposeBag)

        cropVideoVM.preEditBtnObservable.bind(to: cropVideoVM.editStatePublishSubject).disposed(by: disposeBag)

        //editingState events bind

        videoEditSlider.cropCover.leftBar.rx.panGesture().bind(to: cropVideoVM.cropBarPanObserver).disposed(by: disposeBag)

        videoEditSlider.cropCover.rightBar.rx.panGesture().bind(to: cropVideoVM.cropBarPanObserver).disposed(by: disposeBag)

        videoEditSlider.sliderView.rx.willBeginDragging.bind(to: cropVideoVM.sliderBeginDragObserver).disposed(by: disposeBag)

        videoEditSlider.sliderView.rx.didEndDragging.bind(to: cropVideoVM.sliderEndDragObserver).disposed(by: disposeBag)

        videoEditSlider.sliderView.rx.didScroll.bind(to: cropVideoVM.sliderContentDidScrollObserver).disposed(by: disposeBag)

        cropVideoVM.cancelEditBtnObservable.bind(to: cropVideoVM.editStatePublishSubject).disposed(by: disposeBag)

        cropVideoVM.editingDoneBtnObservable.bind(to: cropVideoVM.editStatePublishSubject).disposed(by: disposeBag)

        //finishEditState events bind

        cropVideoVM.backEditingBtnObservable.bind(to: cropVideoVM.editStatePublishSubject).disposed(by: disposeBag)

        bottomBar.doneBtn.rx.tap.bind(to: cropVideoVM.doneBtnTapObserver).disposed(by: disposeBag)

viewModel中部分负责生成可观察对象和观察者及逻辑处理代码

        cropBarPanObserver=Binder(playerLayer.player!) { player, panGesturein

            let translation = panGesture.translation(in: panGesture.view)

            panGesture.setTranslation(.zero, in: panGesture.view)

            player.pause()

            videoEditSlider.cropCover.indicator.isHidden=true

            var offset = translation.x

            if panGesture.view==videoEditSlider.cropCover.leftBar{

                if(videoEditSlider.cropCover.frame.width-offset)

                    offset = videoEditSlider.cropCover.frame.width-SWVideoCropInfo.cropCoverMinW

                }

                if videoEditSlider.cropCover.frame.origin.x+offset <=0{

                    offset = -videoEditSlider.cropCover.frame.origin.x

                }

                videoEditSlider.cropCover.snp.updateConstraints{ (make)in

                    make.left.equalTo(videoEditSlider.cropCover.frame.origin.x+offset)

                }

                player.seek(to: videoEditSlider.cropRange.start)

            }else{

                if(videoEditSlider.cropCover.frame.width+offset)

                    offset = -(videoEditSlider.cropCover.frame.width-SWVideoCropInfo.cropCoverMinW)

                }

                if videoEditSlider.cropCover.frame.maxX+offset >= videoEditSlider.bounds.maxX{

                    offset = videoEditSlider.bounds.maxX-videoEditSlider.cropCover.frame.maxX

                }

                videoEditSlider.cropCover.snp.updateConstraints{ (make)in

                    make.right.equalToSuperview().offset(-(videoEditSlider.bounds.maxX-videoEditSlider.cropCover.frame.maxX-offset))

                }

                player.seek(to: videoEditSlider.cropRange.end)

            }

            if panGesture.state== .ended{

                player.play()

                videoEditSlider.cropCover.indicator.isHidden=false

            }

        }

        doneBtnTapObserver=Binder(cropVideoVC) { vc,_in

            cropVideo(url:SWVideoCropInfo.originUrl, cropRange: videoEditSlider.cropRange) { (croppedUrl, result)in

                if!result {

                    return

                }

                vc.completeHandler!(croppedUrl)

                vc.navigationController?.popViewController(animated:true)

            }

        }

        //MARK: -observable init

        preEditBtnObservable = bottomBar.editBtn.rx.tap.map({

            EditState.editingState

        })

        cancelEditBtnObservable = bottomBar.cancelEditBtn.rx.tap.map({

            EditState.preEditState

        })

        editingDoneBtnObservable = bottomBar.editingDoneBtn.rx.tap.map({

            EditState.finishEditState

        })

        backEditingBtnObservable = bottomBar.backEditingBtn.rx.tap.map({

            EditState.editingState

        })

演示GIF:

详细代码见地址:

https://github.com/JianBinWu/SWSwiftPractice

相关文章

网友评论

      本文标题:RxSwift + MVVM实现仿朋友圈分享视频裁剪功能

      本文链接:https://www.haomeiwen.com/subject/cwcvyhtx.html