H5與iOS交互


H5頁面與原生交互項目中經常遇到,今天做個小結。

從iOS原生的角度講,我們可以使用UIWebViewWKWebView組件來展示H5頁面,那么兩者有什么區別呢?

講述UIWebView只是讓大家了解下這個歷史,按現在的情況我們主要使用WKWebView

一、推出時間

UIWebView從iOS2.0推出到iOS12.0廢棄,WKWebView從iOS8.0推出

UIWebView ios(2.0, 12.0)  、WKWebView ios(8.0)

UIWebView 

UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0)) API_UNAVAILABLE(tvos, macos) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate>

WKWebView

#if TARGET_OS_IPHONE
WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0))
@interface WKWebView : UIView
#else
WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0))
@interface WKWebView : NSView
#endif

二、性能對比

UIWebView

占用過多內存,且內存峰值更是誇張。說白了就是性能低

WKWebView

1、網頁加載速度快,內存消耗低。

2、更多的支持HTML5的特性,

3、高達60fps的滾動刷新率以及內置手勢,

4、Safari相同的JavaScript引擎(但就這一點性能完勝),

5、增加了進度屬性estimatedProgress等特性

三、交互

UIWebView

1、OC調用JS

- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

2、JS調用OC

<1>iOS原生攔截URL

攔截到指定URL做響應操作

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType API_DEPRECATED("No longer supported.", ios(2.0, 12.0));

<2>使用JavaScriptCore實現(要注意循環引用的問題)

JSDelegate
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>

/**
 *  H5會通過對象Bridge調用協議中的方法
 */
@protocol JSDelegate <JSExport>


// 關閉頁面
- (void)finishPage;


@end
JSObject(中間對象,解決循環引用的問題,不直接讓WebViewController遵守JSDelegate的原因)
#import <Foundation/Foundation.h>
#import "JSDelegate.h"
#import "WebViewController.h"

@interface JSObject : NSObject <JSDelegate>

@property(nonatomic, weak) WebViewController *h5VC;

@end
- (void)finishPage {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.h5VC pop];
        });
}
WebViewController
@property (strong, nonatomic) JSContext *jsContext;
// 獲取JSContext,並注入對象
- (void)creatJscontext
{
    //  獲取js上下文(JSContext)
    self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 遵守JSExport協議的對象(符合JSExport的對象都將轉換為JavaScript包裝器對象
    JSObject *obj = [[JSObject alloc] init];
    obj.h5VC = self;
    //  注入交互對象Bridge,H5通過Bridge對象調用JSExport中的方法
    self.jsContext[@"Bridge"] = obj;
}

H5端將通過Bridge.finishPage()調用原生方法

備注:

JSContext
/*!
@interface
@discussion A JSContext is a JavaScript execution environment. All
 JavaScript execution takes place within a context, and all JavaScript values
 are tied to a context.
*/
JS_EXPORT API_AVAILABLE(macos(10.9), ios(7.0))
@interface JSContext : NSObject

UIWebView什么時機創建JSContext環境

什么時候UIWebView會創建JSContext環境,分兩種方式,

第一在渲染網頁時遇到<script標簽時,就會創建JSContext環境去運行JavaScript代碼

第二就是使用方法[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]去獲取JSContext環境時,

這時無論是否遇到<script標簽,都會去創造出來一個JSContext環境,而且和遇到<script標簽再創造環境是同一個。

JSExport
 All objects that conform to JSExport convert to JavaScript wrapper objects,
 even if they subclass classes that would otherwise behave differently. For
 example, if a subclass of NSString conforms to JSExport, it converts to
 JavaScript as a wrapper object rather than a JavaScript string.
*/
@protocol JSExport

 

 
WKWebView
1、OC調用JS
/* @abstract Evaluates the given JavaScript string.
 @param javaScriptString The JavaScript string to evaluate.
 @param completionHandler A block to invoke when script evaluation completes or fails.
 @discussion The completionHandler is passed the result of the script evaluation or an error.
*/
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

2、JS調用OC

<1>iOS原生攔截URL

/*! @abstract Decides whether to allow or cancel a navigation.
 @param webView The web view invoking the delegate method.
 @param navigationAction Descriptive information about the action
 triggering the navigation request.
 @param decisionHandler The decision handler to call to allow or cancel the
 navigation. The argument is one of the constants of the enumerated type WKNavigationActionPolicy.
 @discussion If you do not implement this method, the web view will load the request or, if appropriate, forward it to another application.
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

<2>使用MessageHandler(WKScriptMessageHandler)實現

WKWebView 初始化時,有一個參數叫configuration

它是WKWebViewConfiguration類型的參數,而WKWebViewConfiguration有一個屬性叫userContentController

它又是WKUserContentController類型的參數。

WKUserContentController對象有一個方法- addScriptMessageHandler:name:,我把這個功能簡稱為MessageHandler。

添加或者刪除消息處理

/*! @abstract Adds a script message handler.
 @param scriptMessageHandler The message handler to add.
 @param name The name of the message handler.
 @discussion Adding a scriptMessageHandler adds a function
 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) for all
 frames.
 */
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

/*! @abstract Removes a script message handler.
 @param name The name of the message handler to remove.
 */
- (void)removeScriptMessageHandlerForName:(NSString *)name;

 

收到H5發送的消息

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@class WKScriptMessage;
@class WKUserContentController;

/*! A class conforming to the WKScriptMessageHandler protocol provides a
 method for receiving messages from JavaScript running in a webpage.
 */
@protocol WKScriptMessageHandler <NSObject>

@required

/*! @abstract Invoked when a script message is received from a webpage.
 @param userContentController The user content controller invoking the
 delegate method.
 @param message The script message received.
 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

@end

H5端調用

window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

綜上所述:

最優的方案就是使用WKWebView,交互使用MessageHandler

 參考:

https://www.jianshu.com/p/94bd66874dba

https://www.jianshu.com/p/939db6215436

https://www.jianshu.com/p/f896d73c670a

https://blog.csdn.net/lyyo_cd/article/details/84304864

https://www.jianshu.com/p/79e329ff8953

https://blog.csdn.net/u011619283/article/details/52135988


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM