objc 中最好的多行字符串聲明方式

1. 問(wèn)題

在 AppHost.framework【注1】(以下簡(jiǎn)稱 AppHost) 的編碼中,需要處理很多預(yù)先導(dǎo)入到 webview 里的 js 文件,有一些不關(guān)鍵功能是用 .js 的文件讀到內(nèi)存的,還有一些比較短小的 js 源碼,如;

          (function(e){
                e.setAttribute('src','%@');
                document.getElementsByTagName('body')[0].appendChild(e);
            })(document.createElement('script'));

要寫(xiě)到代碼里和 objc 代碼一起。還有,在 AppHost 里,有個(gè) ah_doc 模塊,在編寫(xiě)注釋時(shí),需要輸出完整的 js 代碼,如

window.appHost.invoke('startNewPage', { 'url': 'http://you.163.com/','title': 'title',
    'type': "push",
    'backPageParameter': {
        'url': 'http://qian.163.com',
        'title': 'title',
        'type': 'push'
    }
})

這個(gè)字符串里包含了大量的單引號(hào)、雙引號(hào),而且為了保持可讀性、維護(hù)性,需要多行輸出。

這是非常典型的問(wèn)題,傳統(tǒng)的多行字符串聲明有沒(méi)有方法很好的解決?

2.常見(jiàn)多行聲明方式

  1. 利用@""包裹起來(lái),換行
NSString *a = @"[AppHost] "
    @"It is called \"jsbridge\"."
    @"like window.ah('ready') = function(){};"
    @"fail to inject javascript";
  1. 利用""包裹起來(lái),換行
NSString *b = @"[AppHost] "
    "It is called \"jsbridge\"."
    "like window.ah('ready') = function(){};"
    "fail to inject javascript";
  1. 最最常見(jiàn)的 \ 號(hào)分隔,保留縮進(jìn)(注意觀察截圖里的 linenum 和代碼的距離

    \分隔符,保留縮進(jìn)

  2. 最最常見(jiàn)的 \ 號(hào)分隔,不保留縮進(jìn)(注意觀察截圖里的 linenum 和代碼的距離

    \分隔符,不保留縮進(jìn)

  3. 非多行

NSString *d = @"[AppHost] It is called \"jsbridge\".like window.ah('ready') = function(){};fail to inject javascript";

輸出結(jié)果

結(jié)果

可見(jiàn),對(duì)于 a\b\c1\d 變量的值而言等價(jià)的。對(duì) c,有個(gè)陷阱:實(shí)際上獲得的字符串是包含編輯器縮進(jìn)。我們現(xiàn)在基本都會(huì)讓編輯器自動(dòng)縮進(jìn)代碼,所以容易出錯(cuò)。

上面 4 種寫(xiě)法,都需要處理字符" 引號(hào)嵌套的問(wèn)題,或者需要手動(dòng)加 " 號(hào),或手動(dòng)寫(xiě) \ 號(hào),要么一行損失掉可讀性。
作者一般用 d 方法:在 vscode 里寫(xiě)好 JavaScript 代碼,放在 sublime text 里 先replace("\"","\\\""),然后command+j 合并行,再貼到Xcode 里。直到我發(fā)現(xiàn)無(wú)意中創(chuàng)建的一個(gè)宏完美的解決了這個(gè)問(wèn)題。

ah_doc_code(window.appHost.invoke('startNewPage', { 'url': 'http://you.163.com/','title': 'title',
    'type': "push",
    'backPageParameter': {
        'url': 'http://qian.163.com',
        'title': 'title',
        'type': 'push'
    }
}))

優(yōu)點(diǎn)

  1. 多行,保存源碼中的縮進(jìn)和換行
  2. 單雙引號(hào)混排,不需要轉(zhuǎn)義
  3. 使用簡(jiǎn)單,只需要包含在對(duì)()中,甚至都不需要外層加雙引號(hào)、#號(hào)(NSString)
  4. 神似 ruby 中的多行字符串聲明(以下代碼是 AppHost 里生成自動(dòng)測(cè)試用例的片段)
    ruby 中的多行字符串

3. 那個(gè)宏 lei 了

#define ah_ml(str) @#str

??簡(jiǎn)單的令人發(fā)指。用例:

result = [NSString stringWithFormat:ah_ml((function(e){
                e.setAttribute("src",'%@');
                document.getElementsByTagName('body')[0].appendChild(e);
            })(document.createElement('script'));), urlToRequest.absoluteString];

查看預(yù)處理的代碼,代碼e.setAttribute("src",'%@');里的引號(hào)自動(dòng)轉(zhuǎn)義。

result = [NSString stringWithFormat:@"(function(e){ e.setAttribute(\"src\",'%@'); document.getElementsByTagName('body')[0].appendChild(e); })(document.createElement('script'));", urlToRequest.absoluteString];

完美呈現(xiàn)。

4.注

  1. AppHost.framework 是作者在網(wǎng)易有錢(qián)、嚴(yán)選工作中,抽離出來(lái) JSBridge 的庫(kù),實(shí)現(xiàn) native 和 h5 之間的通訊,內(nèi)置諸多常用的功能,在業(yè)務(wù)簡(jiǎn)單的情況下可開(kāi)箱即用,復(fù)雜情況允許靈活定制。預(yù)計(jì)在4月底開(kāi)源。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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