1 Star 2 Fork 1

zhengran / MVVM-RAC

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

仿面包旅行(ReactiveCocoa+MVVM)

此项目是将面包旅行跟面包猎人两个应用结合。用ReactiveCocoa+MVVM,最开始想用公司项目,但考虑到要脱敏,不方便。项目中的所有接口都是抓包,只是用来学习练手之用。

注意:直接运行项目出现 xxx not found 的错误,请先cd到项目路径下执行:pod update 即可。


ReactiveCocoa

ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的框架,RAC具有函数式编程和响应式编程的特性。现在ReactiveCocoa已经到RAC5,支持swift3,由于项目是使用的OC,所以我使用的是ReactiveCocoa2.5。如果你的项目是纯OC,也可以使用ReactiveObjC

ReactiveCocoa的函数式编程方式的学习成本比较大,想要学习ReactiveCocoa的可以看这里

MVVM

MVVM是一个UI设计模式。它是MV模式集合中的一员。MV模式还包含MVC(Model View Controller)、MVP(Model View Presenter)等。这些模式的目的在于将UI逻辑与业务逻辑分离,以让程序更容易开发和测试。其中 ViewModel 的主要职责是处理业务逻辑并提供 View 所需的数据,这样 VC 就不用关心业务,自然也就瘦了下来。ViewModel 只关心业务数据不关心 View,所以不会与 View 产生耦合,也就更方便进行单元测试。

MVVM.png

MVVM模式依赖于数据绑定,由于iOS没有数据绑定框架。但幸运的是ReactiveCocoa可以很方便的实现这个,所以ReactiveCocoa是实现MVVM的最佳方式。不通过ReactiveCocoa也可以实现MVVM一样可以实现,感兴趣的可以看这篇博客

更新日志

1.17

  • 增加发现模块的视频播放页面
  • 增加webview导航栏类型

1.18

  • 增加发现模块顶部等多视频页面
  • 增加发现模块活动评论页面

运行效果

首页

@implementation HTCityTravelNotesController

#pragma mark - Life Cycle

- (instancetype)initWithViewModel:(HTCityTravelViewModel *)viewModel
{
    if (self = [super init]) {
        _viewModel = viewModel;
        
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = SetColor(251, 247, 237);
    
    [self setNavigationBar];
    
    [self bindViewModel];

}
#pragma mark - bind
- (void)bindViewModel
{
    self.isSearch = NO;
    
    [self.viewModel.travelCommand execute:@1];
    
    self.bannerView.imageURLSignal = RACObserve(self.viewModel, bannerData);
    
    self.tripBindingHelper = [HTTableViewBindingHelper bindingHelperForTableView:self.tripTableView sourceSignal:RACObserve(self.viewModel, travelData) selectionCommand:nil templateCell:@"HTCityTravelCell"];
    
    
    @weakify(self);
    // 下拉刷新
    self.tripTableView.mj_header = [HTRefreshGifHeader headerWithRefreshingBlock:^{
        @strongify(self);
        [self.viewModel.travelCommand execute:@1];
    }];
    [[self.viewModel.travelCommand.executing skip:1] subscribeNext:^(NSNumber * _Nullable executing) {
        @strongify(self);
        if (!executing.boolValue) {
            [self.tripTableView.mj_header endRefreshing];
        }
    }];
    
    // 加载更多
    self.tripTableView.mj_footer = [HTRefreshGifFooter footerWithRefreshingBlock:^{
        @strongify(self);
        [self.viewModel.travelMoreDataCommand execute:@1];
    }];
    [[self.viewModel.travelMoreDataCommand.executing skip:1] subscribeNext:^(NSNumber * _Nullable executing) {
        @strongify(self);
        if (!executing.boolValue) {
            [self.tripTableView.mj_footer endRefreshing];
        }
    }];
    
    // 搜索框
    [[self
      rac_signalForSelector:@selector(textFieldDidBeginEditing:)
      fromProtocol:@protocol(UITextFieldDelegate)]
    	subscribeNext:^(RACTuple *tuple) {
            @strongify(self)
            if (tuple.first == self.searchTextField){
                
                [self.rightButton setImage:[UIImage imageNamed:@""] forState:UIControlStateNormal];
                [self.rightButton setTitle:@"取消" forState:UIControlStateNormal];
                self.isSearch = YES;
            }
        }];
    [[self rac_signalForSelector:@selector(textFieldDidEndEditing:) fromProtocol:@protocol(UITextFieldDelegate)] subscribeNext:^(RACTuple *tuple) {
        
        @strongify(self)
        if (tuple.first == self.searchTextField){
            
            self.isSearch = NO;
            [self.rightButton setImage:[UIImage imageNamed:@"tabbar_user_button_image_22x22_"] forState:UIControlStateNormal];
            [self.rightButton setTitle:@"" forState:UIControlStateNormal];
        }
    }];
    
    RAC(self.viewModel,isSearch) = RACObserve(self, isSearch);
    
    // 导航栏navigationItem
    self.rightButton.rac_command = self.viewModel.rightBarButtonItemCommand;
    
    [self.viewModel.rightBarButtonItemCommand.executionSignals.switchToLatest subscribeNext:^(NSNumber *isSearch) {
        
        @strongify(self)
        if ([isSearch boolValue]) {
            [self.searchTextField resignFirstResponder];
        }else{
            NSLog(@"进入个人中心");
        }
        
    }];
}

city.png

发现

@implementation HTFindViewController

#pragma mark - Life Cycle
- (instancetype)initWithViewModel:(HTFindViewModel *)viewModel
{
    if (self = [super init]) {
        _viewModel = viewModel;
        
    }
    return self;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = SetColor(250, 250, 250);
    self.navigationItem.title = @"发现";
    
    [self bindViewModel];
}

#pragma mark - bind
- (void)bindViewModel
{
    // findTableView
    self.findBindingHelper = [HTTableViewBindingHelper bindingHelperForTableView:self.findTableView sourceSignal:RACObserve(self.viewModel, feedData) selectionCommand:self.viewModel.feedDetailCommand templateCell:@"HTFindFeedCell"];
    
    // 刷新viedeoView
    self.videoView.modelSignal = RACObserve(self.viewModel, videoData);
    
    @weakify(self);
    // 下拉刷新
    self.findTableView.mj_header = [HTRefreshGifHeader headerWithRefreshingBlock:^{
        @strongify(self);
        [self.viewModel.feedDataCommand execute:@1];
    }];
    [[self.viewModel.feedDataCommand.executing skip:1] subscribeNext:^(NSNumber * _Nullable executing) {
        @strongify(self);
        if (!executing.boolValue) {
            [self.findTableView.mj_header endRefreshing];
        }
    }];
    
    // 加载更多
    self.findTableView.mj_footer = [HTRefreshGifFooter footerWithRefreshingBlock:^{
        @strongify(self);
        [self.viewModel.feedMoreDataCommand execute:@1];
    }];
    [[self.viewModel.feedMoreDataCommand.executing skip:1] subscribeNext:^(NSNumber * _Nullable executing) {
        @strongify(self);
        if (!executing.boolValue) {
            [self.findTableView.mj_footer endRefreshing];
        }
    }];
    
    [self.viewModel.feedDataCommand execute:@1];
}

find.png finddetail.png

运行环境

  • iOS 8+
  • Xcode 8+

空文件

简介

比较牛的例子 展开 收起
Objective-C
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Objective-C
1
https://gitee.com/jiayazi/MVVM-RAC.git
git@gitee.com:jiayazi/MVVM-RAC.git
jiayazi
MVVM-RAC
MVVM-RAC
master

搜索帮助

14c37bed 8189591 565d56ea 8189591