使用SDK

初始化

JSBridge 的初始化,需要在配置 TMFJSBridgeConfiguration 中注册需要使用的 JS API,通过 -[TMFJSBridgeConfiguration registerFunction:withInvocationClass:] 来完成注册:

+ (instancetype)sharedConfiguration;
- (BOOL)registerFunction:(NSString *)function withInvocationClass:(Class)invocationClass;

示例代码

TMFJSBridgeConfiguration *configuration = [TMFJSBridgeConfiguration sharedConfiguration];
[configuration registerFunction:@"echo" withInvocationClass:[TMFJSBridgeInvocation_echo class]];

功能介绍

管理 H5 容器

通过加载 JSBridge 脚本来完成 Web 页面与客户端交互通讯。达到在客户端执行命令,监听客户端事件等功能。

前提条件

若要管理 H5 容器,必须先完成组件的初始化,详情请参见 初始化

创建容器

初始化入口方法,使用一个 UIViewController 实例初始化一个 TMSJSBridge 实例:

- (instancetype)initWithWebViewController:(UIViewController<TMFJSBridgeWebViewControllerProtocol> *)webViewController;
  • 参数
参数 类型 描述 必选
webViewController UIViewController * 实现了 TMFJSBridgeWebViewControllerProtocol 协议 UIViewController 对象,用于注入 TMFJSBridge 脚本。
详见 「TMFJSBridgeWebViewControllerProtocol 协议」
Y
  • TMFJSBridgeWebViewControllerProtocol 协议

    @protocol TMFJSBridgeWebViewControllerProtocol <NSObject>
    
    @property (nonatomic, retain, readonly) __kindof UIView *tmf_webView;
    
    @property (nonatomic, retain) TMFJSBridge *tmf_JSBridge;
    
    @end
    
    • 属性
属性 类型 描述
tmf_webView __kindof UIView * 用于展示内容的界面
tmf_JSBridge TMFJSBridge * 用于处理 JS API 的 JSBridge
  • 返回值
类型 描述
TMFJSBridge * 新创建的 JSBridge 实例,用于处理 JS API 请求

关闭容器

停止 JSBridge 服务接口,用来清除当前已经注入的 TMFJSBridge 脚本,取消监听:

- (void)clearWebViewControllerAndCancel;

脚本注入

主动向当前 H5 容器注入 TMFJSBridge.js 脚本,注入成功后就可以进行 H5 容器管理:

- (void)injectJSBridgeIntoWebView:(nullable void(^)(BOOL success))completion;
  • 参数
参数 类型 描述 必选
completion Block 注入完成回调
详见下方“completion 回调”
N
  • completion 回调
参数 类型 描述 必选
success BOOL 是否完成脚本注入 Y

事件处理

可以通过下面接口判断当前的 URL 是否可以被 TMFJSBridge 解析:

- (BOOL)canHandleURL:(NSURL *)URL;
  • 参数
参数 类型 描述 必选
URL NSURL * 需要判断是否能够解析的 URL 链接 Y
  • 返回值
类型 描述
BOOL 当前链接是否可以被 TMFJSBridge 处理

当判断一个 URL 可以被 TMFJSBridge 解析后,可以通过下面接口来完成注入操作:

- (void)handleURL:(NSURL *)URL;
  • 参数
参数 类型 描述 必选
URL NSURL * 需要解析的 URL 链接 Y

主动事件

客户端也可以通过接口主动发起事件:

- (void)notifyWithEvent:(NSString *)event parameters:(nullable NSDictionary *)parameters;
  • 参数
参数 类型 描述 必选
event NSString * 发起的事件名称 Y
parameters NSDictionary * 发起的事件需要传递的参数,在 H5 容器中会被解析为 json。 N

Helper

TMFJSBridge 提供了便捷工具接口,可以通过此接口便捷注入自定义 javascript 脚本:

- (void)evaluateJavaScript:(NSString *)javaScript completionHandler:(nullable void (^)(
  _Nullable id result, 
  NSError * _Nullable error))completionHandler;
  • 参数
参数 类型 描述 必选
javaScript NSString * 使用字符串构成的自定义 javascript 脚本 Y
completionHandler Block 注入自定义脚本后的回调,包含错误信息等
详见下方“completionHandler 回调”
N
  • completionHandler 回调
参数 类型 描述 必选
result id 注入自定义脚本的处理结果 N
error NSError * 注入自定义脚本的失败信息 N

其他属性

TMFJSBridge 提供了获取当前 URL / Controller / Cache / ContainerID / Title 等属性与方法:

- (nullable NSURL *)webViewURL; // 获取当前 H5 容器 URL 地址
属性 类型 描述 权限
webViewController UIViewController * 当前 H5 容器控制器。需要实现 TMFJSBridgeWebViewControllerProtocol 协议 readonly
containerID NSUInteger 当前 H5 容器的页面 ID。 readonly
cache NSDictionary * 当前 H5 容器的缓存。 readonly
属性 类型 描述 权限
WebViewController_defaultTitle NSString * 当前 H5 容器控制器的默认标题。 readwrite
WebViewController_showsWebTitle BOOL 当前 H5 容器控制器是否展示标题。 readwrite

使用示例

管理 H5 容器的步骤:

  • 创建一个实现 TMFJSBridgeWebViewControllerProtocol 协议的 UIViewController
  • 在当前 UIViewController 中实例化 TMFJSBridge 实例。
  • 在当前 UIViewController 中处理 URL 请求,并实现 UIWebViewDelegate 协议。
  • UIWebView 回调方法里 注入 JSBridge.js 脚本,处理 URL 注入。

下面是创建一个拥有 TMFJSBridge 管理 H5 容器能力的 WkWebViewController 示例:

#import "TMFJSBridge.h"

// 创建一个实现了 TMFJSBridgeWebViewControllerProtocol 协议的 UIViewController
// 这里实现 WkWebViewDelegate 协议目的是为了注入脚本
@interface TMFJSBridgeWKWebViewController : UIViewController <WKUIDelegate,WKNavigationDelegate, TMFJSBridgeWebViewControllerProtocol>

@property (nonatomic, strong, readonly) WkWebView *webView;

- (instancetype)initWithURL:(NSURL *)URL;

@end

@interface TMFJSBridgeWKWebViewController ()

@property (nonatomic, strong) NSURL *URL;
@property (nonatomic, strong) WKWebView *webView;

@end

@implementation TMFJSBridgeWKWebViewController

@synthesize tmf_JSBridge = _tmf_JSBridge;

- (instancetype)initWithURL:(NSURL *)URL
{
    self = [super init];
    if (self) {
        // 初始化 TMFJSBridge 实例
        self.URL = URL;
        self.tmf_JSBridge = [[TMFJSBridge alloc] initWithWebViewController:self];

        self.title = @"TMFJSBridge Demo";
    }
    return self;
}

- (void)dealloc
{
    self.webView.delegate = nil;

    // 在页面生命周期结束 关闭并清理 TMFJSBridge 服务
    [self.tmf_JSBridge clearWebViewControllerAndCancel];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 创建 H5 容器 - WkWebView
    WkWebView *webView = [[WkWebView alloc] initWithFrame:self.view.frame];
    webView.delegate = self;
    self.webView = webView;
    [self.view addSubview:self.webView];

    NSURLRequest *request = [NSURLRequest requestWithURL:self.URL];
    [self.webView loadRequest:request];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // 主动向 H5 容器传递事件
    [self.tmf_JSBridge notifyWithEvent:@"containerAppear" parameters:nil];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    // 主动向 H5 容器传递事件
    [self.tmf_JSBridge notifyWithEvent:@"containerDisappear" parameters:nil];
}

#pragma mark - WkWebViewDelegate

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSURLRequest *request = navigationAction.request;

    // Handle the JSBridge operation if it can
    if ([self.tmf_JSBridge canHandleURL:request.URL]) {
        [self.tmf_JSBridge handleURL:request.URL];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }

    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
{
    // Inject TMFJSBridge into webView
    [self.tmf_JSBridge injectJSBridgeIntoWebView:nil];
}

#pragma mark - TMFJSBridgeWebViewControllerProtocol

- (UIView *)tmf_webView
{
    return self.webView;
}

@end

NS_ASSUME_NONNULL_END

容器初始化完成后,通过以下方式唤起一个 TMF H5 容器:

- (void)createJSBridgeWkWebViewController
{
    NSString *URLString = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"htm"];
    NSURL *URL = [NSURL fileURLWithPath:URLString];
    TMFJSBridgeWkWebViewController *webViewController = [[TMFJSBridgeWkWebViewController alloc] initWithURL:URL];
    [self.navigationController pushViewController:webViewController animated:YES];
}

demo

自定义 JSAPI 功能

根据自身业务需求自定义 JSAPI ,基于自定义 JSAPI 功能,在 H5 容器完成特定的需求。

前提条件

若要进行自定义 JSAPI 创建与使用,必须先完成组件初始化,详情请参见 初始化

方法调用

JS API 的执行方法,由子类负责实现。

- (void)invokeWithParameters:(nullable NSDictionary *)parameters;
  • 参数
参数 类型 描述 必选
parameters NSDictionary * 当前方法注入的参数 N
  • invoke 结束回调

    在 invoke 完成时,子类必须调用如下方法之一来保证闭环:

    // 成功
    - (void)finishWithValues:(nullable NSDictionary *)values completed:(BOOL)completed;
    // 失败
    - (void)failWithValues:(nullable NSDictionary *)values completed:(BOOL)completed;
    

    此方法会把 invoke 的返回值回调到 Web 页面。

    • 参数
参数 类型 描述 必选
values NSDictionary * 完成回调参数,用于回调给 Web 页面 N
completed BOOL 是否完成 JS API 的执行:
1. 若为 YES,则会内部调用 -[TMFJSBridgeInvocation complete] 方法
2. 若为 NO,在 JS API 任务结束后需要由子类主动调用 -[TMFJSBridgeInvocation complete] 方法
3. 在此以前,子类仍然可以通过调用 --[TMFJSBridgeInvocation callbackWithIdentifier:values] 进行自定义回调回调自定义方法
Y
  • 注意事项

    当 Web 页面调用某个 JS API 时,JSBridge 内部会执行此方法。因此,子类或其他调用者不应该调用此方法。在 invoke 完成时,子类必须调用 -[TMFJSBridgeInvocation finishWithValues:completed:]-[TMFJSBridgeInvocation failWithValues:completed:] 来完成功能闭环。

方法回调

此方法回调 JS API parameters 参数里的回调函数。可以通过此方法完成自定义回调。

- (void)callbackWithIdentifier:(id)identifier values:(nullable NSDictionary *)values;
  • 参数
参数 类型 描述 必选
identifier id 回调标识 Y
values NSDictionary * 回调给 H5 页面的参数值 N
  • 注意事项:回调标识

    例如,JS 执行了如下代码:

    TMFJSBridge.invoke('xxx', { progress: function(args) {} })
    

    则在 JS API 对应的 invocation 子类中,在 -[TMFJSBridgeInvocation invocationWithParameters:] 的实现中,用以下方式可以回调 progress 方法:

    [self callbackWithIdentifier:parameters[@"progress"] values:values];
    

完成方法调用

此方法用于完成 JS API 的执行。

- (void)complete;

在 invoke 的所有任务完成时,子类必须要调用此方法。JSBridge 收到 complete 通知后,将会销毁当前 invocation 实例,此后,invocation 的所有执行将停止,无法再向 Web 页面进行回调。

取消执行

此方法用于取消 JS API 的执行。

- (void)cancel;

当 Web 页面被退出时,JSBridge 内部会执行此方法。因此,子类或其他调用者不应该调用此方法。

使用示例

流程步骤:

  • 建立自定义 JSAPI 的扩展类。
    • 命名规范:建议采取 TMFJSBridgeInvocation_functionName 的命名方式。
    • 前置条件:需要引入 "TMFJSBridgeInvocation+Protected.h" 头文件。
    • 类实现:扩展类需要继承于 TMFJSBridgeInvocation
    • 方法实现:- [TMFJSBridgeInvocation invokeWithParameters:]
  • 在 TMFJSAPIs_Custom.h 文件引入自定义 JSAPI 扩展类的头文件。
  • 在 AppDelegate.m 文件的 prepareJSBriget 方法中注册自定义 JSAPI 。
    • 命名规范:建议采取 TMFJSBridgeInvocation_functionName 中的 functionName 作为函数名注册。
  • 后续使用,在 H5 页面中调用自定义的 JSAPI。
  • 基于 Safari 查看调试信息,看自定义 JSAPI 是否符合预期。

下面以获取上报地理位置为例:

#import "TMFJSBridgeInvocation.h"

@interface TMFJSBridgeInvocation_reportCurrentLocation : TMFJSBridgeInvocation

@end
@implementation TMFJSBridgeInvocation_reportCurrentLocation

- (void)invokeWithParameters:(NSDictionary *)parameters {
        NSMutableDictionary *returnValue = [NSMutableDictionary dictionary];

        // 此处省略客户端获取地理位置的逻辑代码
      NSString *location = @"中国";
    if (location) {
        returnValue[@"location"] = location;
    }

    [self completeWithReturnValue:@(0) extendedValue:returnValue];
}

- (void)cancel
{
    // 中断客户端获取地理位置的异步方法
}
#ifndef TMFJSAPIs_Custom_h
#define TMFJSAPIs_Custom_h

// TMFJSAPIs_Custom 中引入头文件 (也可以自行才使用处引用)
#import "TMFJSBridgeInvocation_reportCurrentLocation.h"

#endif /* TMFJSAPIs_Custom_h */
// AppDelegate.m 中注册自定义 JSAPI
TMFJSBridgeConfiguration *configuration = [TMFJSBridgeConfiguration sharedConfiguration];
[configuration registerFunction:@"reportCurrentLocation" withInvocationClass:[TMFJSBridgeInvocation_reportCurrentLocation class]];

H5安全键盘扩充

前提条件

已经参考 管理 H5 容器 进行容器的初始化配置。

引入头文件

#import "TMFJSBridgeInvocation_safeKeyboardDisplay.h"

遵守协议

遵守<TMFSafeKeyboardWrapperWebViewControllerDeleate>协议

@interface TMFJSBridgeWKWebViewController : QDCommonViewController <WKUIDelegate,WKNavigationDelegate, TMFJSBridgeWebViewControllerProtocol, TMFSafeKeyboardWrapperWebViewControllerDeleate>

声明属性

声明属性codeViewKeyboardWrapper

@property (nonatomic, strong) TMFSafeKeyboardWrapper *codeViewKeyboardWrapper;

初始化属性

// keyboard
self.codeViewKeyboardWrapper = [[TMFSafeKeyboardWrapper alloc] initWithKeyboard:TMFSafeKeyboard.new];
[self.codeViewKeyboardWrapper setKeyboardDelegate:self];

实现协议方法

#pragma mark - keyboard
- (BOOL)safeKeyboardShouldReturn:(TMFSafeKeyboard *)safeKeyboard{
    return YES;
}
- (void)safeKeyboardUpdateViewConstraints:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardWillAppear:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardDidAppear:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardWillDisappear:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardDidDisappear:(TMFSafeKeyboard *)safeKeyboard {}

使用示例

@interface TMFJSBridgeWKWebViewController : QDCommonViewController <WKUIDelegate,WKNavigationDelegate, TMFJSBridgeWebViewControllerProtocol, TMFSafeKeyboardWrapperWebViewControllerDeleate>

@property (nonatomic, strong, readonly) TMFWkWebView *webView;
@property (nonatomic, strong) TMFSafeKeyboardWrapper *codeViewKeyboardWrapper;      // 键盘设置

- (instancetype)initWithURL:(NSURL *)URL;

@end
- (void)viewDidLoad {
    [super viewDidLoad];

    // 安全键盘
    self.codeViewKeyboardWrapper = [[TMFSafeKeyboardWrapper alloc] initWithKeyboard:TMFSafeKeyboard.new];
    [self.codeViewKeyboardWrapper setKeyboardDelegate:self];

    // 创建 H5 容器 - WkWebView
    WkWebView *webView = [[WkWebView alloc] initWithFrame:self.view.frame];
    webView.delegate = self;
    self.webView = webView;
    [self.view addSubview:self.webView];

    NSURLRequest *request = [NSURLRequest requestWithURL:self.URL];
    [self.webView loadRequest:request];
}


#pragma mark - keyboard
- (BOOL)safeKeyboardShouldReturn:(TMFSafeKeyboard *)safeKeyboard{
    return YES;
}
- (void)safeKeyboardUpdateViewConstraints:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardWillAppear:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardDidAppear:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardWillDisappear:(TMFSafeKeyboard *)safeKeyboard {}
- (void)safeKeyboardDidDisappear:(TMFSafeKeyboard *)safeKeyboard {}
Copyright © 2013-2023 Tencent Cloud. all right reserved,powered by GitbookUpdate Time 2023-08-31 14:46:07

results matching ""

    No results matching ""