React Native - iOS Native 回調(diào)

( Native 方法理解為 iOS/Android 原生代碼 )
在真實的使用場景中,不僅僅只是調(diào)用下Native的方法,還需要對結(jié)果進(jìn)行處理,Native處理完之后返回結(jié)果再回調(diào)會JavaScript中進(jìn)行操作和處理。
這樣就需要使用JavaSctipt的回調(diào)函數(shù),對結(jié)果進(jìn)行處理。在React Native中Object-c有兩種方式的回調(diào):RCTReponseSenderBlockPromises。

1.RCTReponseSenderBlock

在JavaScript和Object-C的參數(shù)列表,有一類參數(shù)叫做RCTReponseSenderBlock對應(yīng)JavaScript的Function,這個就是JavaScript調(diào)用Object-C的Callback(回調(diào)函數(shù))。

RCTReponseSenderBlock是在RCTBridgeModule.h定義的block.
完整的定義:

typedef void (^RCTResponseSenderBlock)(NSArray *response);

RCTReponseSenderBlock定義個一個Object-C Bridge的操作,返回給JavaScript一個callback的方法。

他的參數(shù)是一個NSArray。其中第一個參數(shù)是error代表著錯誤信息,如果沒有錯誤傳入null,后面的參數(shù)傳入自定義的內(nèi)容。
具體實例:
先給UIAlertView添加兩個按鈕,在點擊按鈕之后使用RCTResponseSenderBlock返回JavaScript。
先實現(xiàn)UIAlertViewDelegate

@interface RNIOSAlert : NSObject<RCTBridgeModule,UIAlertViewDelegate>
@end

定義一個變量用來保存參數(shù):

@implementation RNIOSAlert{
  RCTResponseSenderBlock _alertCallback;
}
@end

在clickedButtonAtIndex方法中處理結(jié)果并調(diào)用回調(diào)函數(shù):

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    switch (alertView.tag) {
        case 0:
            if (buttonIndex == 0) {
                _alertCallback(@[@"取消"]);
            }else{
                _alertCallback(@[[NSNull null],@"確定"]);
            }
            break;
        default:
            break;
    }
}

最后定義帶有回調(diào)參數(shù)的Native方法:(把 alertView 放在主線程中顯示,否則會卡頓,一段時間后才能顯示出)

RCT_EXPORT_METHOD(showAlertViewAndMsg:(NSString *)message Callback:(RCTResponseSenderBlock) alertCallback){
    _alertCallback = alertCallback;
    dispatch_sync(dispatch_get_main_queue(), ^{
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"React Native" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"繼續(xù)", nil];
        alert.tag = 0;
        [alert show];
    });
}

最在JavaScript中調(diào)用Native方法,并處理回調(diào):

_alertCallback() {
    RNIOSAlert.showAlertAndCallback(function (err, datas) {
        if (err) {
            console.warn('err', '已取消');
        } else {
            console.warn('data', '請繼續(xù)');
        }
    });
}

每次關(guān)閉UIAlertView都可以看到JavaScript處理的結(jié)果。

2.Promises

Promises是ES6中的特性,它的目的是統(tǒng)一為JavaScript提供異步編程的接口,避免Callback地獄,解決了Callback的層層嵌套。更加容易的對異步操作進(jìn)行控制。詳解參考:React Native - Promise 對象
在React Native中對Promises有很完善的支持,調(diào)用Object-C 的Native方法的時候,也可以Promise的方式讓代碼執(zhí)行從Object-C 回到JavaScript中。
先看Promises的兩個狀態(tài)。

Resolve和Reject是Promise的兩種狀態(tài),表示已解決和已拒絕,

  • Resolve是已解決的執(zhí)行結(jié)果,會觸發(fā)then操作
  • Reject是已拒絕的執(zhí)行結(jié)果,會觸發(fā)catch操作
    在Object-C與之相對應(yīng)的是:RCTPromiseResolveBlockRCTPromiseRejectBlock,兩個都是定義好的Object-C bridge。

RCTPromiseResolveBlock的實現(xiàn):

typedef void (^RCTPromiseResolveBlock)(id result);

以id為參數(shù),當(dāng)然傳參必須是Object-c和JavaScript定義好的參數(shù)。
RCTPromiseRejectBlock的實現(xiàn):

typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error);

RCTPromiseRejectBlock使用了NSError,還可以傳入自定義的code以及message。

 NSError * error =[NSError errorWithDomain:@"test" code:0 userInfo:nil];
使用Promise實現(xiàn)回調(diào)

首先要定義兩個變量用來保存參數(shù):

@implementation RNIOSAlert{
    RCTPromiseResolveBlock _resolveBlock;
    RCTPromiseRejectBlock _rejectBlock;
}

在定義提供給JavaScript調(diào)用的Native函數(shù):


RCT_REMAP_METHOD(alertUsePromise,resolve:(RCTPromiseResolveBlock)resolve
                 reject:(RCTPromiseRejectBlock)reject){
    _resolveBlock = resolve;
    _rejectBlock = reject;
    
    dispatch_sync(dispatch_get_main_queue(), ^{
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"React Native " message:@"使用Promise實現(xiàn)回調(diào) alertUsePromise" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"繼續(xù)", nil];
        alert.tag = 1;
        [alert show];
    });
}

這里使用RCT_REMAP_METHOD宏定義Native,他的第一個參數(shù)是方法名,后面的參數(shù)是方法的實現(xiàn),在JavaScript調(diào)用Promise時并不需要在方法名中體現(xiàn)。
處理結(jié)果并使用回調(diào):

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 0) {
        NSError * err=[NSError errorWithDomain:@"test" code:0 userInfo:nil];
        _rejectBlock(@"0",@"cancel",err);
    }else{
        _resolveBlock(@[@"成功"]);
    }
}

JavaScript中調(diào)用該方法:

_alertUsePromise() {
     RNIOSAlert.alertUserPromise().then((datas)=> {
         console.warn('data', datas);
     }).catch((err)=> {
         console.warn('err', err);
     });
 }

這里的then處理的是Resovle狀態(tài)的結(jié)果,而catch處理的是Reject狀態(tài)的結(jié)果。
也可以使用async/await實現(xiàn)

async  _alertPromise() {
     try {
         var datas = await RNIOSAlert.alertUserPromise();
         console.warn('data', datas);
     } catch (e) {
         console.warn('err', e);
     }
 }

async/await是兩個關(guān)鍵詞,用來把Promises的思想融入到語言本身。使用他們就不再需要寫catch這樣的偽同步的代碼,直接使用try/catch/return這樣的關(guān)鍵詞就可以了.
Promises對于回調(diào)的使用很便利,盡量避免了JavaScript的回調(diào)地獄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內(nèi)容