GithubHelp home page GithubHelp logo

shenyanjun / breadtrip-reactivecocoa-mvvm- Goto Github PK

View Code? Open in Web Editor NEW

This project forked from binbear/breadtrip-reactivecocoa-mvvm-

1.0 2.0 0.0 7.22 MB

仿面包旅行,ReactiveCocoa+MVVM

Objective-C 99.84% Ruby 0.16%

breadtrip-reactivecocoa-mvvm-'s Introduction

仿面包旅行(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

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

2.28

  • 增加JSPatch以及网络状态的判断
  • 增加折叠的tabbar样式

运行效果

首页

@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+

breadtrip-reactivecocoa-mvvm-'s People

Contributors

binbear avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.