最近在学习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:

详细代码见地址:
网友评论