你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 客戶端動態化系列之——URLRoute

客戶端動態化系列之——URLRoute

編輯:IOS開發基礎

對於客戶端來說,發版本身就屬於一種很高成本的行為。然而一個初創的app,會有各式各樣的問題,而在初期也不會像大型app一般有一套成熟的處理異常機制。而這往往會造成許多問題,那麼問題來了,如何在有限的開發資源下,做到客戶端的動態化。並且實現降級、ABTest等等一系列的行為呢?

What we want?

如前文提到,當版本迭代時,首當其沖的就是版本的問題。作為團隊的開發,我曾經花了很多時間在思考一個問題。如何能讓我們的架構模型變得優雅,變得像橡皮泥一般能隨著業務的發展迅速變形,特別是在一個創業公司,迫切需要一個強大的架構體系能支撐業務的快速發展。

那麼事情就變得很簡單了,在維持業務發展速度不變的情況下,盡可能減少發版的頻率,以技術的方式在不發版的情況下滿足“偽發版”。

當然,還有其他的一些想法,會在後文提到:

  • ABTest

  • 灰度

  • 降級策略

  • 動態調用本地服務

What to do?

有了想法知道,思路就比較清晰了,會針對性的對目的進行處理。

“偽發版”

對於app來說,偽發版的方案已經在業內比較成熟了。我們可以用weex/react native(以同一JS代碼,在H5、iOS、Android同時實現同一頁面)的方式來實現在不發版的情況下實現頁面級別的更新。

我們試想一下,雖然weex實現了頁面的動態更新。但是卻沒法很優雅地處理新頁面與老頁面的跳轉關系。打個比方,一個native頁面A已經在代碼裡寫死點擊按鈕跳轉頁面B,此時就算用weex/rn寫了一個新頁面,也是很難跳轉的(當然如果兩個頁面都是weex/rn寫的,就不會存在這樣的問題,但是在大多數應用場景裡,還是會存在部分weex/rn,部分native的頁面)。

即 A -> B 是一個既定的關系。為了達到動態化,必然需要對整個app的導航進行統一處理。
這就是URLRoute要做的事情!


正如其名,URLRoute會有一個路由規則

URLRoute

而動態化的秘訣就是將無法變動的邏輯代碼維護成文本。即 代碼 -> 文本 。

文本沒有編譯、簽名等等發版需要的步驟,它的更新完全是可以由文件的更新完成,而這恰恰是不需要發版的。

拿iOS為例,我實現了一個URLRoute的庫,其中的處理流程可以由下圖所示:


其中URL與對應的class的映射是由一個文件維護的,如圖所示:


通過維護一個dictionary(map)維護URL與本地頁面或服務的關系。

ABTest && 灰度

任何業務在發展的階段都不可避免會產生分歧,此時需要如果業務架構支持對不同的人群命中不同粒度的產品,並且給出數據以展示哪一種結果更好,這對於思考產品的人有更多的選擇余地。

而通過URLRoute,我們完全可以針對不同的人群派發不同的映射文件達到ABTest的目的。

甚至在某一個版本上可以做到灰度,10%->20%->...->100%。

降級策略

試想一下,如果以上線的項目產生了重大BUG怎麼辦。對於iOS來說,可以通過Runtime的方式達到patch。但是對於Android來說,現有的三種方案:classloader,更改jar包,更改apk。後兩者更不用說,我們並不是一個apk。而前者在現如今的動態方案中逐漸被拋棄。其實都不適合我們,這些其實都需要一套完整的解決方案,並不僅僅是導入庫就行,還要考慮與server的交互等。

那麼如何做到一個方式,能以最簡單的方式做到在產生BUG時,以最小的成本並且在兩端以同樣的策略去做到修復或者降級呢?

答案是我們可以通過更改映射文件,將原先有問題的URL對應的value替換掉,即A->B變成A->C(C可以是一個error頁面,也可以是一個weex/rn頁面)。當然你會問如果本地沒有實現C怎麼辦?沒關系,我們刪掉那條URL記錄,當URLRoute攔截不到URL時,會以webview的形式打開,這樣就降級成H5了


動態調用本地服務

URLRoute不僅僅處理了頁面之間的跳轉邏輯,也可以處理service。這裡的service可以理解為任何native的行為,比如登錄、強制更新、發網絡請求等等

我們可以事先注冊好對應的module,通過URL調用對應的service

這是很重要的,比如我們產生了重大BUG,我們就可以強制登出用戶,甚至強制所有頁面都跳到error頁面等等

How to do?

我們可以在要實現URLRoute的class,在plist文件裡聲明,key為對應的host + path,value為對應的class name

// 默認調用方式
OpenURL(@"http://m.kuailejim.com/home?id=552131");
// 如果需要傳URL不能表達的參數(Object參數)
OpenURLWithParams(@"http://m.kuailejim.com/home?id=552131", paramsDictionary);

這裡的scheme為http,是因為我在URLRoute裡做了處理,當這裡的key(m.kuailejim.com/home)沒有被攔截到即在plist文件中並沒有找到對應的class來處理時,我會判斷scheme是否為http/https,如果是,則會跳到H5以實現降級

我們知道,URL傳參對於object類型是不友好的,於是需要實現一個能帶dictionary(map)的方法,並且在URLRoute內部實現基於key/value形式參數的解析。

對應的class需要實現下述方法,這樣URLRoute通過runtime動態創建對應的class,並且調用class已經實現的代理方法達到處理的效果:

- (id)initWithUrlRequest:(URLRouteRequest *)request;

這裡還需要注意,在URLRoute裡要hook對應的viewdidappear方法來拿到當前的view controller,才能做到push和model的操作。如果是model操作還需實現一個navigation controller(因為有可能會在新的頁面裡push)

AOP統一處理,例如想在跳轉時對所有url記錄埋點等功能,這個很好理解,只要在URLRoute裡在實現攔截前統一做處理就行

總結

這只是客戶端動態化的第一步,baby steps to big dreams

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved