寫給 Web 端同事的一些iOS知識分享

此次分享主要分爲兩個部分:javascript

  • iOS 相關開發知識的一些介紹,以便你們之後接觸到相似 RN / Flutter 工程但沒有移動端同事的時候,可以有方向去搜相關信息;
  • iOS 端與 web 端相互調用和調試的一些概括。

因爲分享過程當中間會穿插使用Xcode進行演示和口頭講解,文章只作了部分關鍵信息的羅列html

系統層次架構圖

主要分爲4個層次:Cocoa TouchMediaCore ServiceCore OSjava

iOS Foundation Layer.png

  • Cocoa Touch 觸摸UI層 顧名思義,其包含的不少框架是與用戶交互相關的,是開發 iOS App 的關鍵框架。提供了 App 的基礎結構,同時也提供了諸如:觸摸、推送、多任務處理、推送等系統服務。ios

    其中 UIKit 是最經常使用的,用於界面的構建。git

  • Media 媒體層 提供對 App 處理各類媒體文件的處理能力,諸如:音視頻的編解碼,圖形繪製,製做動畫效果等。github

  • Core Services 核心服務層 包含全部 App 使用的基本系統服務。即便不直接使用這些服務,系統的許多部分仍是創建在它們之上。web

    其中 Foundation 是最經常使用的,爲上層框架和App開發提供基礎功能,提供基本的數據類型和操做工具,諸如:集合類型處理、字符串處理、日期處理、文件處理、異常處理等。json

  • Core OS 核心操做系統層 包含大多數其餘技術所基於的底層功能。負責內存管理、文件系統任務、網絡處理和一些其餘的操做系統任務,還能直接和硬件設備進行交互。一般來講,大部分開發狀況不會直接使用與這一層打交道,上層框架會使用到它們。設計模式

更多可見 iOS Technology Overview -TP40007898 7.0.3-數組

基本知識概覽

基本知識概覽.png

工程文件

鑑於通常Web開發者會接觸到iOS工程的狀況是使用React-Native/Flutter/Weex初始化時自動建立的項目,因此先來看看工程文件都有些什麼:

  • *.h: 頭文件,聲明類、方法以及屬性,至關於對外暴露可訪問接口。
  • *.m: 實現 .h 中聲明的方法,添加私有方法、屬性。
  • *.pch: 預編譯頭文件,一般用於放置 宏定義公共頭文件


  • *.xib: 可視化View佈局文件,本質是使用XML描述的View佈局文件
  • *.storyboard: 故事板,xib的強化版,一樣是使用XML描述的佈局文件,但可放置、鏈接控制多個頁面跳轉邏輯
  • *.plist: 全稱Property List(屬性列表),可用於存儲序列化後的對象,經常使用用於存儲用戶配置,輕量級的持久化方案
  • *.lproj: 國際化包,可包含文本圖片xibstoryboard
  • *.xcassets: (圖片)資源文件包,一般用於放置圖片資源,後續增長了顏色


  • Podfile: 普遍使用的包依賴管理(Cocoapods)的配置文件,可類比成web項目的package.json
  • *Podfile.lock: 依賴管理工具安裝依賴的鎖定版本,可類比成web項目的package-lock.json


  • *.xcodeproj: Xcode 工程文件,存儲工程的各類配置
  • *.xcworkspace: Xcode 工程文件,一般是使用依賴管理工具 Cocoapods 執行 pod install 安裝了依賴以後生成的(也可本身搞,是多個 xcodeproj 的合集)。

設計模式

光禿禿的直接解釋也不能很好的理解,因此藉着設計模式的示例工程來了解一下。

不過仍是有一些須要先講一講便於理解

相似 NS、UI、AV、CF的前綴是什麼?

因爲在 OC 中沒有命名空間的概念,因此經過加前綴的方式來避免衝突,通常開發者用本身名字/公司縮寫的大寫字母做爲前綴,Apple保留全部2個字母做爲前綴的權利。 其中 NS 表明的是NeXTSTEP,是喬布斯創立的 NeXT.Inc 公司開發的系統,其原生支持Objective-C,NeXT 1997年被 Apple 被收購,成爲Mac OS的基礎。 其餘諸如:UI -> UIKit、 AV -> AVFoundation/AVKit(Audio+Video)、CF -> CoreFoundation

@ 是什麼?

一是關鍵字前帶@,如:@class@interface@implementation@end@protocol 等等 二是做爲語法糖,如字符串 @""、基礎類型轉對象類型的數字@(1) @(YES) @(0.0)、數組 @[]、字典 @{}

演示

詳見示例工程,此段主要爲分享中講解,文章中沒有體現


接下來咱們來講說 iOS 和 web 端開發協調相關的東西。

WebView 與 Native交互

在 iOS 中有兩種webview,UIWebViewWKWebView

  • UIWebView (iOS 2.0 ~ 12.0) 在App進程中跑,加載頁面的內存是算在App佔用內存中的,當app內存超過限制時,會通知app處理,若未處理整個app會被kill。 已成歷史,2020年4月開始禁止新的App使用,年末禁止全部含有的App更新。

  • WKWebView (iOS 8.0 ~ ) 獨立進程,當其內存佔用超過系統分配給WKWebView的內存時,WKWebView會崩潰白屏並通知app進行處理,未處理app不會被kill。內存是 UIWebView 的1/3 - 1/4,啓動更快。異步處理與native橋接通訊的js。


固然 WKWebView 也是有不少坑點的:
  • 雖然從iOS 8.0開始支持,可是有不少問題,因此通常會從9.0纔開始使用。不過鑑於iOS用戶更新率很是高(從目前官方數據來看 50%的iPhone已是iOS 13了, 41%的iOS12),這個基本能夠忽略了。
  • Cookie會出現攜帶不上的問題。
  • 經過loadRequest發起post請求的body會被丟掉。
  • 直接使用NSURLProtocol沒法攔截請求。

碰上的主要是這幾個,更多其餘的能夠參考bugly的WKWebView 那些坑

URL攔截,經常使用Scheme

相似於 mhc://b.maihaoche.com?type=xxx&value=xxx

<html>
    <header>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript"> // 給Native調用執行的方法 定義好 function showAlert(message){ alert(message); } // 經過發起iframe的方式打開一個 url-scheme function loadURL(url) { var iFrame; iFrame = document.createElement("iframe"); iFrame.setAttribute("src", url); iFrame.setAttribute("style", "display:none;"); iFrame.setAttribute("height", "0px"); iFrame.setAttribute("width", "0px"); iFrame.setAttribute("frameborder", "0"); document.body.appendChild(iFrame); // 發起請求後這個 iFrame 就沒用了,因此把它從 dom 上移除掉 iFrame.parentNode.removeChild(iFrame); iFrame = null; } // 點擊html按鈕 function firstClick() { loadURL("mhc://b.maihaoche.com?type=xxx&value=xxx"); } </script>
    </header>

    <body>
        <h2> scheme </h2>
        <button type="button" onclick="firstClick()">Click Me!</button>
    </body>
</html>
複製代碼

Universal Links

須要服務器進行配置,可參考 iOS9 Universal Links踩坑之旅,移動應用之deeplink喚醒app

JavaScriptCore

僅UIWebView可用

  • web 端實現
<html>
    <header>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript"> function secondClick() { // 調用native定義的方法 nativeShare('分享的標題','分享的內容','圖片地址'); } </script>
    </header>

    <body>
        <h2> JSCore </h2>
        <button type="button" onclick="secondClick()">Click Me!</button>
    </body>
</html>
複製代碼
  • iOS 端實現
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 暴露給 web 調用的原生方法 nativeShare
    context[@"nativeShare"] = ^() {
        NSArray *args = [JSContext currentArguments];
        for (JSValue *val in args) {
            NSLog(val.toString);
        }
    };
}
複製代碼

WKWebView

  • Web 端實現
function btnClick() {
    // window.webkit.messageHandlers.方法名.postMessage(傳參數);
    window.webkit.messageHandlers.nativeShare.postMessage('params');
}
複製代碼
  • iOS 端實現
// 監聽web方法
- (void)setupScriptHandler{
    [self.wkWebView.configuration.userContentController addScriptMessageHandler:self name:@"nativeShare"];
}

// 執行 web 調用 native
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"nativeShare"]) {
        // web傳遞過來的參數
        NSLog(message.body);
        
        // objc 執行 web 方法
        [self.wkWebView evaluateJavaScript:@"alert(\"分享成功\")" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            // web callback
        }];
    }
}
複製代碼

WebViewJavascriptBridge

抹平UIWebView、WKWebView差別 WebViewJavascriptBridge

移動端調試 webview

單純在pc端使用手機視圖模式,有時並不能保證其在 移動端瀏覽器/App 有一致的表現,那麼要怎麼調試呢?

準備工做

須要對Mac/iOS端Safari進行簡單的設置

  • Mac Safari

mac_safari_open_develop_menu.png

  • iOS Safari

ios_safari_webcheck.jpeg

開始調試

調試分兩種狀況,web頁是跑在 Safari 中仍是 App 中的,但不管如何都須要先把手機和電腦鏈接起來(無線鏈接跟局域網複雜程度有關,有的時候連不上,在家裏還行,在公司就別了)。

在 Safari 中打開的 web 頁

好比,在手機端Safari打開 www.baidu.com,會看到Mac端的Safari-開發-手機-多了以下圖的選項

safari_debug_select_iphone.png

打開後能夠看到下圖彈出一個常見的web檢查器工具,大部分操做點我相信大家比我熟悉,在這裏就提幾個小技巧吧:

  1. 圖中紅色框的工具,點擊後(呈現藍色狀態的瞄準鏡),能夠直接在手機上點擊web元素來觸發選中
  2. 當鼠標滑過web元素(如綠色框的代碼)的時候能夠看到手機端也會有對應的元素框標識
  3. 選中的web元素/代碼/執行後的代碼,後面會有= $* (* = 0、一、2.....),能夠直接的控制檯使用它

safari_debug_baidu.png

在 App 中打開的 web 頁

首先,須要確認你手機的App是經過開發的同窗 使用Xcode直接Debug Run出來的(掃碼分發下載的不支持),或者模擬器使用拖進去的包也可(但記得給檢查一下模擬器的Safari的網頁檢查器是否打開)

safari_debug_app_webview.png

使用web內嵌工具

web開發者也能夠直接在web項目中內嵌一個開發工具,好比:

一些資料

human-interface-guidelines

WWDC-Videos

iOS Programming Tricks

一份走心的JS-Native交互電子書.pdf

Websites for iPhoneX

DarkMode in Webkit

相關文章
相關標籤/搜索