ios鏈式開發(fā) oc 移除項目中的delegate,讓block實現(xiàn)鏈式調用,讓調用更簡單

之前發(fā)現(xiàn)了一種類似block串行執(zhí)行的開發(fā)方式,今天終于不忙了就簡單寫一下做個筆記


鏈式調用

其實很簡單,需要注意的就是相應對象的返回值,如下拿 person 和boy兩個對象舉例,最后實現(xiàn) person.person(NO).strongMan(@"強壯的小男孩").boy(@"小男孩兒開始說").speak(@"我想回家");

Person.h

#import <Foundation/Foundation.h>
@class Boy;
@interface Person : NSObject
@property (nonatomic,readonly) Person *(^person)(BOOL enable);
@property (nonatomic,readonly) Person *(^strongMan)(NSString *str);
@property (nonatomic,readonly) Boy *(^boy)(NSString *str);
@end

Person.m

#import "Person.h"
#import "Boy.h"
@implementation Person
-(Person *(^)(BOOL))person{
    return ^(BOOL enable){
        NSLog(@"Person Say:%d\n",enable);
        return self;
    };
}

-(Person *(^)(NSString *))strongMan{
    return ^(NSString *str){
        NSLog(@"%@\n",str);
        return self;
    };
}

-(Boy *(^)(NSString *))boy{
    return ^(NSString *str){
        NSLog(@"%@\n",str);
        return [[Boy alloc]init];
    };
}
@end

boy.h

#import <Foundation/Foundation.h>
@interface Boy : NSObject
@property (nonatomic,readonly)Boy *(^speak)(NSString *speakStr);
@end

boy.m

#import "Boy.h"
@implementation Boy
-(Boy *(^)(NSString *))speak{
    return ^(NSString *speakStr){
        NSLog(@"speak:%@\n",speakStr);
        return self;
    };
}
@end

vc調用--------------------------------------------------

- (void)viewDidLoad {
    [super viewDidLoad];
    person.person(NO).strongMan(@"強壯的小男孩").boy(@"小男孩兒開始說").speak(@"我想回家");
}
打印結果

一般的使用到此就結束了,下面來稍微加點難度,前面的我們都看到了,都是正向傳值,都是調用方直接告訴被調用方要干什么什么,那么我們如果需要調用方回傳一些數(shù)據(jù)做處理呢,大家自己思考一下再往下看

思路是這樣的,既然要反向且又想鏈式,那么自然想到了block,我們在被調用方的參數(shù)中修改參數(shù)為block是否能實現(xiàn)呢,繼續(xù)往下看

拿系統(tǒng)定位功能CLLocationManager來做例子,調用定位,我們首先要檢查權限、設置參數(shù)、開始定位、然后定位代理成功回調處理、失敗處理這幾個功能,我們最終的實現(xiàn)結果需要是這樣的

    self.locationManager.checkAuthorization(NO).startLocation().locationSuccess(^(NSDictionary *addressDict) {
        NSLog(@"定位成功");
    }).locationError(^(NSError *error){
        NSLog(@"定位失敗");
    });

1.首先我們聲明這幾個block

###JoyLocationManager.h
@property (nonatomic,readonly)JoyLocationManager *(^checkAuthorization)(BOOL backGroundModel);
@property (nonatomic,readonly)JoyLocationManager *(^startLocation)();
@property (nonatomic,readonly)JoyLocationManager *(^stopLocation)();
//參數(shù)為idblock類型(我這是定義的id類型參數(shù)的回調)
@property (nonatomic,copy)JoyLocationManager    *(^locationSuccess)(IDBLOCK block);
//參數(shù)為idblock類型(我這是定義的error類型參數(shù)的回調)
@property (nonatomic,copy)JoyLocationManager    *(^locationError)(ERRORBLOCK block);
2.這幾個block
###JoyLocationManager.m
#pragma mark 檢查權限
-(JoyLocationManager *(^)(BOOL))checkAuthorization{
    return ^(BOOL backGroundModel){
        [self checkAuthorStateAndSetBackModel:backGroundModel];//檢查權限并設置是否后臺運行模式
        return self;
    };
}

#pragma mark 開始定位
-(JoyLocationManager *(^)())startLocation{
    return ^(){
        [self startManagerLocation];//開始定位
        return self;
    };
}

#pragma mark 結束定位
-(JoyLocationManager *(^)())stopLocation{
    return ^(){
        [self stopManagerLocation];  //結束定位
        return self;
    };
}
#pragma mark 定位成功
-(JoyLocationManager *(^)(IDBLOCK block))locationSuccess{
    return ^(IDBLOCK block){
//runtime關聯(lián)對象,定位成功代理中回調參數(shù)
        objc_setAssociatedObject(self, _cmd, block, OBJC_ASSOCIATION_COPY);
        return self;
    };
}
#pragma mark 定位失敗
-(JoyLocationManager *(^)(ERRORBLOCK))locationError{
    return ^(ERRORBLOCK block){
//runtime關聯(lián)對象,定位失敗代理中回調參數(shù)
        objc_setAssociatedObject(self, _cmd, block, OBJC_ASSOCIATION_COPY);
        return self;
    };
}

#pragma mark 定位代理   
//CLLocation這個類里面包括的一些常用的位置信息有經度、緯度、海拔、速度、精確度
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
  //定位成功進行地理反編碼,可以改進一下考慮自行加入到鏈中
    [self reverseGEOCodeLocation:locations.firstObject];
    [self stopManagerLocation];
}
//定位失敗
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
//拿到前面關聯(lián)的block并回調參數(shù)
    ERRORBLOCK successBlock = objc_getAssociatedObject(self, @selector(locationError));
    successBlock?successBlock(error):nil;
}
//反地理編碼
- (void)reverseGEOCodeLocation:(CLLocation *)location{
    CLGeocoder *revGeo = [[CLGeocoder alloc] init];
    [revGeo reverseGeocodeLocation:location
                 completionHandler:^(NSArray *placemarks, NSError *error) {
                     if (!error && [placemarks count] > 0)
                     {
                         NSDictionary *dict =
                         [[placemarks objectAtIndex:0] addressDictionary];
                         IDBLOCK successBlock = objc_getAssociatedObject(self, @selector(locationSuccess));
                         successBlock?successBlock(dict):nil;
                     }else{
                         NSLog(@"ERROR: %@", error);
                     }
                 }];
}

到此可以試試了

self.locationManager.checkAuthorization(NO).startLocation().locationSuccess(^(NSDictionary *addressDict) {
        NSLog(@"定位成功");
    }).locationError(^(NSError *error){
        NSLog(@"定位失敗");
    });

成功回走成功的回調,失敗會走失敗的回調,大家可以自行去試試把定位精度、headupdate、地理編碼等試試加進來

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • iOS代碼塊Block 概述 代碼塊Block是蘋果在iOS4開始引入的對C語言的擴展,用來實現(xiàn)匿名函數(shù)的特性,B...
    smile刺客閱讀 2,375評論 2 26
  • Block使用場景,可以在兩個界面的傳值,也可以對代碼封裝作為參數(shù)的傳遞等。用過GCD就知道Block的精妙之處。...
    Coder_JMicheal閱讀 740評論 2 1
  • iOS網絡架構討論梳理整理中。。。 其實如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
    yhtang閱讀 5,259評論 1 23
  • 《Objective-C高級編程》這本書就講了三個東西:自動引用計數(shù)、block、GCD,偏向于從原理上對這些內容...
    WeiHing閱讀 9,908評論 10 69
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,993評論 19 139