我廠廣招各路大神加入:job.koudaitong.com
能夠發簡歷到 tianchi@qima-inc.com O(∩_∩)O~git
今天從杭州回家錯過了高鐵,又改爲了客車。原本很是懊惱的心情,看到文章被SF博客轉發了,一會兒就行了起來。segmentfault
最近閒着也是爲了下一個與TX的小夥伴合做的項目作準備,作了一個簡單的APP。主要的功能就是設定一個目的地,在你快要到達目的地的時候給你提醒。對於我這種坐動車常作過站的人來講,恩,時候是拯救本身一把了。框架
項目的結構很簡單,以下圖所示:異步
項目使用了MVVM的框架結構來替代MVC框架。storyboard中的內容以下:async
第一個界面爲保存的路線,選擇以後直接進入出發頁面,新增路線以後點擊出發一樣進入出發頁面。在出發頁面中點擊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則在收到錯誤信號後……呃……打印了那個錯誤……
恩……男人是否是不能這麼快……好吧,此次先寫到這兒,好睏啊,明天項目正式動工,先早點休息了。
下次爲你們繼續新建路線中的內容。(其實和這個用法大同小異
)
代碼寫的到不到的還請多多包含,最好能幫忙指出錯誤!小弟謝過了。