ReactiveCocoa簡單實戰 (一)

ReactiveCocoa簡單實戰

我廠廣招各路大神加入:job.koudaitong.com
能夠發簡歷到 tianchi@qima-inc.com O(∩_∩)O~git

前戲

今天從杭州回家錯過了高鐵,又改爲了客車。原本很是懊惱的心情,看到文章被SF博客轉發了,一會兒就行了起來。segmentfault

最近閒着也是爲了下一個與TX的小夥伴合做的項目作準備,作了一個簡單的APP。主要的功能就是設定一個目的地,在你快要到達目的地的時候給你提醒。對於我這種坐動車常作過站的人來講,恩,時候是拯救本身一把了。框架

欲露還羞

項目的結構很簡單,以下圖所示:異步

Project

項目使用了MVVM的框架結構來替代MVC框架。storyboard中的內容以下:async

storyboard

第一個界面爲保存的路線,選擇以後直接進入出發頁面,新增路線以後點擊出發一樣進入出發頁面。在出發頁面中點擊changeBtn(就是那個沒顯示全的按鈕,恩,偷懶了)能夠修改提示音樂。出發頁面中會計算當前位置與目的地的直線距離,以及估算的到達時間(如今APP裏面好像算錯了,正在改正)ide

正戲開始

首先,將高德地圖的SDK配置好以後,來看看第一個頁面--ChooseViewController的內容:atom

#import "ChooseViewController.h"
#import "ChooseViewModel.h"
#import <AMapSearchKit/AMapSearchObj.h>
#import "OnRoadViewController.h"
#import <PromiseKit/PromiseKit.h>

@interface ChooseViewController ()
@property (nonatomic,strong) ChooseViewModel *viewModel;
@property (nonatomic,strong) NSDictionary *targetInfoDic;
@end

@implementation ChooseViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    _viewModel = [ChooseViewModel new];
    self.tableView.delegate   = _viewModel;
    self.tableView.dataSource = _viewModel;

    [_viewModel.cellSelectedSignal subscribeNext:^(id x) {
        if (x) {
            //tiaozhuan
            _targetInfoDic = x;
            [self performSegueWithIdentifier:@"SelectToGo" sender:self];
        }
    }];

    [_viewModel.loadRoutesFromCache subscribeNext:^(id x) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData];
        });
    } error:^(NSError *error) {
        NSLog(@"%@",error.description);
    }];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if ([segue.identifier isEqualToString:@"SelectToGo"]) {
        CGPoint location = [_targetInfoDic[@"target"] CGPointValue];
        NSDictionary *info = _targetInfoDic[@"target_info"];
        AMapPOI *targetPoi = [[AMapPOI alloc] init];
        AMapGeoPoint *mgp = [AMapGeoPoint locationWithLatitude:location.x longitude:location.y];
        targetPoi.location = mgp;
        targetPoi.name = info[@"name"];
        targetPoi.address = info[@"address"];
        targetPoi.type = info[@"type"];
        OnRoadViewController *onRoadVC = (OnRoadViewController *)[segue destinationViewController];
        onRoadVC.targetPoi = targetPoi;
    }
}
@end

很簡單的一段代碼。在匿名類別中添加了兩個對象,一個就是ViewModel,另外一個用來儲存目的地的經緯座標的字典。spa

viewDidLoad中,咱們將tableview的delegate與dataSource都設爲了剛剛new出來的viewModel。而且咱們分別對viewModel中的cellSelectedSignal信號與loadRoutesFromCache信號綁定了next的處理事件。線程

那麼咱們就來看看這兩個事件究竟是怎麼起做用的吧。在ChooseViewModel中,這兩個信號分別是這樣子的:code

-(RACSignal *)loadRoutesFromCache;

@property (nonatomic,strong) RACSubject *cellSelectedSignal;

在對象被new的時候,咱們實例化了cellSelectedSignal信號:

+(id)new{
    ChooseViewModel *model = [super new];
    model.cellSelectedSignal = [RACSubject subject];
    return model;
}

(不知道這樣寫有沒有問題)它一個RACSubject對象,subject的特色就是信號的發送是可控的。下面就來看看這個信號是怎麼可控的吧:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [self.cellSelectedSignal sendNext:self.waysDic[self.routesArr[indexPath.row]]];
}

咱們使用了sendNext:方法將waysDic中的路徑信息經過信號發送了出去。在ChooseViewController中註冊的next處理事件便會獲得執行。在其中,咱們儲存了目的地信息吼將頁面push到下一個頁面,在push以前咱們構建了一個poi對象(高德SDK),並傳遞了過去。

接下來看看那個從文件中讀取內容的信號吧(loadRoutesFromCache)。

-(RACSignal *)loadRoutesFromCache{
    RACSubject *subject = [RACSubject subject];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSData *data = [NSData dataWithContentsOfFile:kWaysSavePath];
        NSMutableDictionary *waysDic = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        if(waysDic!=nil && [waysDic allKeys].count>0){
            self.waysDic = waysDic;
            self.routesArr = [waysDic allKeys];
            [subject sendNext:_routesArr];
            [subject sendCompleted];
        }else{
            [subject sendError:[NSError errorWithDomain:@"rb.loadroutes" code:0 userInfo:@{@"error": @"未能加載"}]];
        };
    });
    return subject;
}

這個信號被表示成了一個方法,這個方法返回了一個Subject對象。在異步執行完成後,向這個Subject對象發送next與completed信號,若是內容不存在則發送error信號。VC中(實際上是view)中的next處理事件在收到信號後回到主線程刷新tableview;error則在收到錯誤信號後……呃……打印了那個錯誤……

這麼快就沒了

恩……男人是否是不能這麼快……好吧,此次先寫到這兒,好睏啊,明天項目正式動工,先早點休息了。

下次爲你們繼續新建路線中的內容。(其實和這個用法大同小異)

代碼寫的到不到的還請多多包含,最好能幫忙指出錯誤!小弟謝過了。

相關文章
相關標籤/搜索