Rickenbacker
👌. MVVM + RxSwift + Mediatror + MJRefresh + DZNEmptyDataSet + SkeletonView
英文 | 简体中文
这是一个基于 MVVM + RxSwift 的基础设施集
功能
目前,Rickenbacker 最重要的功能可以总结如下
适配器
此模块主要用于封装基类。
- BaseViewController: 支持OC基类,公开部分。
- VMScrollViewController: 为列表提供刷新和空数据显示支持。
- VMTableViewController: 列表基类,内部响应处理。
- VMViewController: 您需要指定 ViewModel 或其子类作为泛型。
- ViewModel: 基础视图模型,子类必须继承。
- NavigationBarHiddenable:隐藏导航栏的协议。
CatHome
资源模块,主要负责图像资源和文本资源读取。
- 读取图像资源
R.image("base_black_back")
- 读取文本资源
R.text("base_empty_title")
- 读取颜色资源
R.color("background")
BeeBox
主要收集RxSwift相关的有用类和方法等。
Mediatror
-
此模块主要提供设计组件中间层。
-
还有两种更典型的设计组件中间层的方案
- 基于URL注册跳转方法,参考蘑菇街开源MGJRouter
- 基于Objective-C运行时的中介方法,参考CTMediator
-
简要介绍两种方法的优缺点
- URL注册的方式非常繁琐,而且通常并不必要。首先,需要事先注册每个页面跳转的URL,这将涉及大量的字符串硬编码。
- 基于运行时中介的方法,首先不需要注册,这样可以节省大量的字符串对比过程。其次,很容易传递各种参数,用于实现通信。
-
因此,最终的解决方案选择也是
Mediator
方法;
测试用例:
if let vc = Mediator.Second_viewController(title: "biaoti") {
pushButton.rx.tap
.bind(to: rx.pushViewController(vc, animated: true))
.disposed(by: disposeBag)
}
- 组件化中间层
extension Mediator {
static func Second_viewController(title: String) -> UIViewController? {
self.perform(target: SecondTarget.self,
action: "setupSecondViewController",
module: "Rickenbacker_Example",
params: ["title": title])
}
}
class SecondTarget: NSObject {
/// Note prompt, `@objc` must be added here.
@objc func setupSecondViewController(_ params: NSDictionary) -> UIViewController? {
guard let title = params["title"] as? String else { return nil }
let vm = SecondViewModel.init(title: title)
let vc = SecondViewController.init(viewModel: vm)
return vc
}
}
HBDNavigationBar
本模块基于对底层的导航基础封装的HBDNavigationBar。
MJRefresh
本模块基于MJRefresh封装的UITableView刷新功能。
- 注入刷新功能,只需简单地实现
ViewModelHeaderable
协议。 - 注入加载更多功能,只需简单地实现
ViewModelFooterable
协议。
测试用例
extension MJRefreshViewModel: ViewModelHeaderable, ViewModelFooterable {
var enterBeginRefresh: Bool {
return false
}
// Automatic non-sensing pull-up refresh function
var footer: MJRefreshFooter {
let footer = MJRefreshAutoFooter()
footer.triggerAutomaticallyRefreshPercent = -5
return footer
}
}
备注:当然,您也可以根据需要自定义
header
和footer
。
DZNEmptyDataSet
本模块基于DZNEmptyDataSet封装的UITableView空数据展示。
- 要注入空数据展示功能,只需简单实现
ViewModelEmptiable
协议。
测试用例
class EmptyViewModel: ViewModel, ViewModelEmptiable, ViewModelHeaderable {
let dataSource: BehaviorRelay<[String]> = BehaviorRelay(value: [])
func loadData() {
let driver = NetworkService().randomResult().asObservable()
driver.bind(to: dataSource).disposed(by: disposeBag)
driver.map { $0.isEmpty }.bind(to: isEmptyData).disposed(by: disposeBag)
driver.subscribe { _ in } onCompleted: {
self.refreshSubject.onNext(.endHeaderRefresh)
}.disposed(by: disposeBag)
}
}
- 这里也支持自定义样式设计,只需要实现
DZNEmptyDataSetSourceable
或DZNEmptyDataSetDelegateable
协议,接口直接对DZNEmptyDataSet
进行操作。
测试用例
// Configure empty data display information
extension DZNEmptyDataSetViewController: DZNEmptyDataSetable {
func DZNEmptyDataSetImage(scrollView: UIScrollView) -> UIImage {
return R.image("base_network_error_black")
}
func DZNEmptyDataSetImageTintColor(scrollView: UIScrollView) -> UIColor? {
return UIColor.red
}
func DZNEmptyDataSetTitle(scrollView: UIScrollView) -> NSAttributedString? {
NSAttributedString(string: R.text("TEXT"))
}
func DZNEmptyDataSetDescription(scrollView: UIScrollView) -> NSAttributedString? {
NSAttributedString(string: R.text("测试网络异常展示"))
}
func DZNEmptyDataSetVerticalOffset(scrollView: UIScrollView) -> CGFloat {
return -77
}
}
CocoaPods
- 如果您想使用此框架,请使用CocoaPods。
pod 'Rickenbacker'
备注
过程大致如此,演示也写得非常详细,您可以去自行查看。🎷
提示:如果您觉得有帮助,请给我点一个星。如果您有任何问题或需求,也可以提出。
谢谢。🎇
关于作者
- 🎷 电子邮件地址:[email protected] 🎷
- 🎸 GitHub地址:yangKJ 🎸
许可协议
Rickenbacker可在MIT许可协议下使用。更多信息请查看LICENSE文件。