iOS鏈?zhǔn)秸Z法深入實踐

要點

1.什么是鏈?zhǔn)秸Z法
2.Block聲明
3.實現(xiàn)&注意問題
4.場景&優(yōu)缺點

什么是鏈?zhǔn)秸Z法

OC中的RAC、Masonry姑曙、SnapKit等鏈?zhǔn)骄幊痰牡湫徒蠼唬蠹覒?yīng)該都熟悉了
Masonry

[testV mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.bottom.left.right.equalTo(self.view);
}];

點語法聲明式的調(diào)用,怎么實現(xiàn)呢伤靠?
----核心點語法和Block結(jié)合
OC并不像其它諸如Swift婿着、JS、Java等語言天然的語法支持醋界,所以我們只能利用OC的點語法來實現(xiàn)鏈?zhǔn)秸{(diào)用的語法糖,實現(xiàn)之前我們要首先對Block的聲明要熟悉

Block聲明

作為類的屬性
@property (nonatomic, copy) returnType (^blockName)(parameterTypes)
方法聲明返回值
- (Test *(^)(NSString *str))blk0;
作為方法參數(shù)
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;

示例
- (void)methodTakesBlock:(void (^)(NSString *))blockName {
    
}

調(diào)用方法時傳入的參數(shù)
[self someMethodThatTakesABlock:^returnType (parameters) {...}];

示例:
-(IBAction)test2:(id)sender {
    [self methodTakesBlock:^(NSString *name) {
        NSLog(@"name:%@",name);
    }];
}

寫在方法里作為局部變量
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
自定義Block類型
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
  • returnType是返回值
  • blockName是block名稱
  • parameterTypes是參數(shù)

實現(xiàn)&注意問題

作者手懶就不拿項目中已有的或者從新寫個小demo了竟宋,這里以Masonry中為例

make.leading.trailing.bottom

對于這部分沒有入?yún)⒌逆準(zhǔn)綄崿F(xiàn)其實很簡單

@property (nonatomic, strong, readonly) MASConstraint *right;
@property (nonatomic, strong, readonly) MASConstraint *bottom;
@property (nonatomic, strong, readonly) MASConstraint *leading;
@property (nonatomic, strong, readonly) MASConstraint *trailing;
@property (nonatomic, strong, readonly) MASConstraint *width;

get方法
- (MASConstraint *)leading {
    return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
}

直接聲明一個屬性返回目標(biāo)對象,然后重寫get方法,我們重點看下equalTo(self.view)

- (MASConstraint * (^)(id attr))equalTo;
- (MASConstraint * (^)(id))equalTo {
    return ^id(id attribute) {
        return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}

現(xiàn)在形纺,我們可以通過點語法調(diào)用getter方法的形式來調(diào)用方法丘侠,但是我們知道,getter方法是無法加參數(shù)的逐样,通過上面block的形式蜗字,調(diào)用get方法等同于執(zhí)行block打肝,調(diào)用block就可以隨意定義并傳入入?yún)ⅰ?br> 這里有些童鞋可能有點疑問make.top.bottom.left.right.equalTo(self.view);
equalTo的聲明是一個方法,能打點調(diào)用嗎挪捕?以及為什么可以粗梭?
我們平時調(diào)用屬性的setter/getter時,都是使用點語法調(diào)用级零,其本質(zhì)也是調(diào)用的方法断医,所以我們驗證下

.h
@interface TestObj : NSObject
- (NSString *)hello;
@end

.m
- (instancetype)init
{
    self = [super init];
    if (self) {
        NSString *helloStr = self.hello;
    }
    return self;
}

我們通過以下轉(zhuǎn)寫成c/c++代碼

xcrun -sdk iphonesimulator clang -rewrite-objc -fobjc-arc -stdlib=libc++ -mios-version-min=12.1 -fobjc-runtime=ios-12.1 -Wno-deprecated-declarations TestObj.m

后我們可以看到

static instancetype _I_TestObj_init(TestObj * self, SEL _cmd) {
    self = ((TestObj *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("TestObj"))}, sel_registerName("init"));
    if (self) {
        NSString *helloStr = ((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("hello"));
    }
    return self;
}
objc_msgSend最后找的SEL “hello”進行消息發(fā)送

或者在“NSString *helloStr = ”這一行下斷點Xcode菜單欄Debug->Debug Workflow->Always show。奏纪。查看匯編實現(xiàn)


222.png

那有的同學(xué)會有疑問聲明屬性和直接聲明方法有什么區(qū)別嗎鉴嗤?
答案還是有區(qū)別的。
主要還是在調(diào)用的時候系統(tǒng)給的友好提示方面序调。屬性聲明時在調(diào)用的時候會提示入?yún)㈩愋妥砉宦暶鞣椒ㄐ问皆谡{(diào)用的時候不會有任何提示,可能會稍有不便


333.png

修改為屬性后:
444.png

需要注意的地方
不管哪種方式发绢,我們都要注意內(nèi)存泄漏問題硬耍,這里主要注意是否循環(huán)引用問題,如果在get方法內(nèi)部返回的block沒有被當(dāng)前類強引用那么在block內(nèi)部可以直接引用self边酒,否則要類似weakSelf等避免循環(huán)引用.

場景&優(yōu)缺點

場景千千萬默垄,任何代碼實現(xiàn)部分理論上都可以鏈?zhǔn)絹韺崿F(xiàn)。重要的是我們要權(quán)衡到底有沒有必要
作者簡單列一些作者用到的場景
1.網(wǎng)絡(luò)請求:

[self requestWithHTTPMethod:@"POST"
                  baseURLString:nil
                           path:pathOrFullURLString
                     parameters:nil
                          files:nil
        accountIdentityRequired:YES
                      usesCache:NO
                           from:nil
            responseObjectClass:responseObjectClass
         uploadProgressReporter:nil
                 succeededBlock:succeededBlock
                    failedBlock:failedBlock];

諸如此類會有很多入?yún)⑸醺伲皇侨雲(yún)⑦^多代碼不夠直觀也不規(guī)范口锭,二是很多入?yún)⒖赡芪幢匦枰獋鳌_@個時候就很需要鏈?zhǔn)秸Z法介杆,按需配置入?yún)⑼瑫r便于閱讀

改版后:

SPTNetworkEngine.spt_dataxEngine.get(@"requestPath")
    .handleJSONResponse(^(id  _Nonnull JSONObject) {
        
    }).handleFailure(^(NSError * _Nonnull error) {
        
    }).start();

需要請求入?yún)⒌臅r候加上即可
.usesAccountIdentity(SPTNetworkAccountIdentityUsageNone)
.withParameters(parameters)

2.項目中特殊業(yè)務(wù)彈窗實現(xiàn)

whiteListView.withViews(targetView, window)
                .withContents(^(SPTChatRoomWhiteListViewConfig * _Nonnull viewConfig) {
                    //viewConfig;//whiteListView配置項交由user配置擴展,不傳則內(nèi)部默認(rèn)配置
                }).selectedAction(^(id<SPTChatRoomWhiteListModelProtocol>  _Nonnull selectedItem) {
                    
                }).cancelAction(^{
                    
                }).show(YES);

以上甚至可以直接調(diào)用.show(YES);

3.甚至比Masonry更深入的autolayout鏈?zhǔn)椒庋b

self.likePKView.sn_centerXToSuperView()
    .sn_topToSuperView().sn_equal(-spt_screen_adaptive_float(52))
    .sn_height(@(spt_screen_adaptive_float(52)))
    .sn_leftToSuperView()
    .sn_rightToSuperView()
    .sn_layout();
  1. ...

以上只是部分作者項目中實踐的場景鹃操。更多的需要我們自己去權(quán)衡,畢竟鏈?zhǔn)秸Z法封裝的代碼總是比基本語法耗時春哨,既要提高開發(fā)效率, 同時也要保證APP運行速度, 所以要量力而行, 不能太泛濫!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荆隘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赴背,更是在濱河造成了極大的恐慌椰拒,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凰荚,死亡現(xiàn)場離奇詭異燃观,居然都是意外死亡,警方通過查閱死者的電腦和手機便瑟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門缆毁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人到涂,你說我怎么就攤上這事脊框“涠剑” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵浇雹,是天一觀的道長沉御。 經(jīng)常有香客問我,道長昭灵,這世上最難降的妖魔是什么吠裆? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮虎锚,結(jié)果婚禮上硫痰,老公的妹妹穿的比我還像新娘衩婚。我一直安慰自己窜护,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布非春。 她就那樣靜靜地躺著柱徙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奇昙。 梳的紋絲不亂的頭發(fā)上护侮,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音储耐,去河邊找鬼羊初。 笑死,一個胖子當(dāng)著我的面吹牛什湘,可吹牛的內(nèi)容都是我干的长赞。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼闽撤,長吁一口氣:“原來是場噩夢啊……” “哼得哆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起哟旗,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤贩据,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后闸餐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饱亮,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年舍沙,在試婚紗的時候發(fā)現(xiàn)自己被綠了近尚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡场勤,死狀恐怖戈锻,靈堂內(nèi)的尸體忽然破棺而出歼跟,到底是詐尸還是另有隱情,我是刑警寧澤格遭,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布哈街,位于F島的核電站,受9級特大地震影響拒迅,放射性物質(zhì)發(fā)生泄漏骚秦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一璧微、第九天 我趴在偏房一處隱蔽的房頂上張望作箍。 院中可真熱鬧,春花似錦前硫、人聲如沸胞得。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阶剑。三九已至,卻和暖如春危号,著一層夾襖步出監(jiān)牢的瞬間牧愁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工外莲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猪半,地道東北人。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓偷线,卻偏偏與公主長得像磨确,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淋昭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351