swift&JS交互 - JavaScriptCore

swift&JS交互 - JavaScriptCore

自從iOS7之后Apple退出JavaScriptCore,極大的方便了iOS與H5的聯(lián)系俘枫。

一疹瘦、JavaScriptCore主要類

JSContext:JSContext是JS的執(zhí)行環(huán)境巡球,通過evaluateScript()方法可以執(zhí)行JS代碼

JSValue: JSValue封裝了JS與ObjC中的對應的類型,以及調(diào)用JS的API等

JSExport: JSExport是一個協(xié)議险胰,遵守此協(xié)議,就可以定義我們自己的協(xié)議棚贾,在協(xié)議中聲明的API都會在JS中暴露出來妙痹,這樣JS才能調(diào)用原生的API

二鼻疮、直接通過JSContext執(zhí)行JS代碼

import JavaScriptCore    //記得導入JavaScriptCore


    let context: JSContext = JSContext()
    let result1: JSValue = context.evaluateScript("1 + 1")
    print(result1)  // 輸出2
        
    // 定義js變量和函數(shù)
    context.evaluateScript("var num1 = 2; var num2 = 3;")
    context.evaluateScript("function multiply(param1, param2) { return param1 * param2; }")
        
    // 通過js方法名調(diào)用方法
    let result2 = context.evaluateScript("multiply(num1, num2)")
    print(result2 ?? "result2 = nil")  // 輸出6
        
    // 通過下標來獲取js方法并調(diào)用方法
    let squareFunc = context.objectForKeyedSubscript("multiply")
    let result3 = squareFunc?.call(withArguments: [2, 3]).toString()
    print(result3 ?? "result3 = nil")  // 輸出6

三判沟、通過JSContext注入模型,然后調(diào)用模型的方法

1挪哄、首先定義一個協(xié)議SwiftJavaScriptDelegate 該協(xié)議必須遵守JSExport協(xié)議

這里必須使用@objc,因為JavaScriptCore庫是ObjectiveC版本的砸彬。如果不加@objc拿霉,則調(diào)用無效果咱扣。定義兩個函數(shù),有參和無參兩個沪铭,帶有參數(shù)的注意補全杀怠。

// 定義協(xié)議SwiftJavaScriptDelegate 該協(xié)議必須遵守JSExport協(xié)議
@objc protocol MallH5BridgeProtocol: JSExport {
    
    /// 登錄
    ///
    /// - Parameter urlString: 登錄成功后跳轉(zhuǎn)的url
    func login(_ urlString: String)
    
    /// 掃碼
    func goToScanCode()
}
2赔退、然后定義一個模型 該模型實現(xiàn)SwiftJavaScriptDelegate協(xié)議

創(chuàng)建一個模型類遵從上面的協(xié)議,如果需要修改UI等相關操作窗骑,我們需要在主線程中操作漆枚。

// 定義一個模型 該模型實現(xiàn)SwiftJavaScriptDelegate協(xié)議
@objc class MallH5Bridge: NSObject, MallH5BridgeProtocol {
    
    weak var controller: MallH5ViewController?
    weak var jsContext: JSContext?
    
    /// js調(diào)用APP登錄
    func login(_ urlString: String) {
        DispatchQueue.main.async {
            [weak webController = self.controller] in
            guard AppLoginUserManager.default.isLogin == false else {
                AppShare.default.showMessage(message: "您已經(jīng)登錄了哦")
                return
            }
            
            AppShare.goToLoginVC(sourceVC: webController) {
                if urlString.count > 0 && urlString != "undefined" {
                    webController?.redirect(toUrl: urlString)
                }
            }
        }
    }
    
    /// 掃碼
    func goToScanCode() {
        DispatchQueue.main.async {
            AppShare.goToGoodsQRCode(source: self.controller)
        }
    }
  
}

3软族、將模型注入到網(wǎng)頁中残制,暴露給JS

注入操作在webViewDidFinishLoad代理方法中。

func webViewDidFinishLoad(_ webView: UIWebView) {
        
        if let jsContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext {
            
            let model = MallH5Bridge()
            model.controller = self
            model.jsContext = jsContext
            
            jsContext.setObject(model, forKeyedSubscript: "WebViewBridge" as NSCopying & NSObjectProtocol)
            
            jsContext.exceptionHandler = { (context, exception) in
                print("exception:", exception as Any)
            }
            self.jsContext = jsContext
        }
        
        stopWebLoading()
    }
4仰禽、JS調(diào)用swift方法

在JS方法中如下調(diào)用即可吐葵。注意這里的WebViewBridge是你在注入時定義的名稱温峭,可以自己設置字支。

//以下為JS中的方法
openScan() {
    (window as any)["WebViewBridge"].goToScanCode()
}

login() {
    (window as any)["WebViewBridge"].login("http://www.baidu.com")
}
5堕伪、swift調(diào)用JS方法

在JS中創(chuàng)建方法sayHello(),最重要的是要將此方法綁定到window下否則swift調(diào)用不到蹄梢。(這里坑了我一天多)

images.jpeg
componentDidMount() {
    (window as any).sayHello = this.sayHello
    (window as any).sayGoodbye = this.sayGoodbye
}

sayHello() {
    alert('hello')
}

sayGoodbye(argument) {
    let name = argument['name']
    alert('goodbye ${name}')
}

當在JS中創(chuàng)建完成后禁炒,swift中如下調(diào)用有參數(shù)和無參數(shù)的JS方法幕袱。

//這里是swift調(diào)用無參數(shù)的JS方法
func sayHello() {
     let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("sayHello")
    jsHandlerFunc?.callWithArguments([])    
}

//這里是swift調(diào)用有參數(shù)的JS方法
func sayGoodbye() {
    let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("sayGoodbye")
    let dict = ["name": "joeal"]
    jsHandlerFunc?.callWithArguments([dict])
}

如果你要在componentDidMount方法中直接調(diào)用原生方法悠瞬,那么可能會發(fā)生找不到方法的錯誤涯捻。其實這是因為方法還未注入完成障癌。你可以延遲一點調(diào)用:

componentDidMount() {
  setTimeout(() => {
        (window as any)["WebViewBridge"].hello();
    }, 2000);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市对省,隨后出現(xiàn)的幾起案子晾捏,更是在濱河造成了極大的恐慌,老刑警劉巖劳秋,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玻淑,死亡現(xiàn)場離奇詭異补履,居然都是意外死亡剿另,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門谚攒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馏臭,“玉大人讼稚,你說我怎么就攤上這事∷苎拢” “怎么了痛倚?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掘鄙。 經(jīng)常有香客問我嗡髓,道長,這世上最難降的妖魔是什么浊伙? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任嚣鄙,我火速辦了婚禮哑子,結(jié)果婚禮上肌割,老公的妹妹穿的比我還像新娘。我一直安慰自己烦却,他們只是感情好先巴,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布伸蚯。 她就那樣靜靜地躺著,像睡著了一般摇幻。 火紅的嫁衣襯著肌膚如雪挥萌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天狂芋,我揣著相機與錄音帜矾,去河邊找鬼。 笑死屡萤,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的招拙。 我是一名探鬼主播措译,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼瞳遍,長吁一口氣:“原來是場噩夢啊……” “哼菌羽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起注祖,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤是晨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蚊逢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箫章,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年终抽,在試婚紗的時候發(fā)現(xiàn)自己被綠了昼伴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡圃郊,死狀恐怖女蜈,靈堂內(nèi)的尸體忽然破棺而出飒泻,到底是詐尸還是另有隱情泞遗,我是刑警寧澤席覆,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站聊倔,受9級特大地震影響生巡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甸陌,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一盐股、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧牲尺,春花似錦幌蚊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臭蚁。三九已至讯赏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間系枪,已是汗流浹背磕谅。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工雾棺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捌浩,地道東北人工秩。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓助币,卻偏偏與公主長得像,于是被迫代替她去往敵國和親眉菱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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