文档

iOS端接入

EMAS提供WindVane供您集成应用,以实现通过WindVane集成H5应用。本文介绍如何在iOS端集成WindVane。

接入SDK

  1. 在podfile文件中指定仓库,添加依赖,并执行pod install或者pod update命令,获取SDK到项目中。

    source 'https://github.com/CocoaPods/Specs.git'
    source 'https://github.com/aliyun/aliyun-specs.git'
    pod 'WindVane' ,'11.2.2.1'
  2. 按照如下配置,初始化SDK。

    @interface EMASWindVaneConfig : NSObject
    + (void)setUpWindVanePlugin;
    @end
    
    @implementation EMASWindVaneConfig
    + (void)setUpWindVanePlugin {
        // 设置APPKey, 如果使用了安全黑匣子, 就会使用安全黑匣子的key
        //[WVUserConfig setAppKey:@"4272"secrect:@"0ebbcccfee18d7ad1aebc5b135ff****"];
        [WVUserConfig setAppKey:[[EMASServiceshareInstance] appkey]];
        // 设置是否使用安全黑匣子
        [WVUserConfig useSafeSecert:NO];
        // 设置环境
        // [WVUserConfigsetEnvironment:WVEnvironmentDaily];
        [WVUserConfig setEnvironment:WVEnvironmentRelease];
        // 设置TTID
        //[WVUserConfig setTTid:@"windvane@****"];
        // 设置UA
        [WVUserConfig setAppUA:[NSStringstringWithFormat:@"TBIOS"]];
        // 设置 App 名称,会在 UserAgent 中带上,请务必正确设置。
        [WVUserConfig setAppName:@"EMASDemo"];
        // 设置App版本
        NSDictionary *infoDictionary =[[NSBundle mainBundle] infoDictionary];
        [WVUserConfig setAppVersion:[infoDictionary objectForKey:@"CFBundleShortVersionString"]];
        // WKWebView 支持 NSURLProtocol
        [WVURLProtocolService setSupportWKURLProtocol:YES];
    
        #ifdef DEBUG
        [WVBasicUserConfig setDebugMode:YES];
        // 打开 WindVane 的 Log
        [WVBasicUserConfig openWindVaneLog];
        [WVUserConfig setLogLevel:WVLogLevelVerbose];
        [WVBasic setJSLogLevel:WVLogLevelVerbose];
        #endif
    
        // 初始化WindVane各模块
        //[WVTBExtension setup];
        [WVBasic setup];
        [WVAPI setup];
        [WVMonitor startMonitoring];
        [EMASWVExtensionConfig setup];
    
    }
    @end

    AppDelegate.m文件的application:didFinishLaunchingWithOptions方法中,调用以下代码,初始化SDK。

    - (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        [self initZCacheConfig]; 
        [EMASWindVaneConfig setUpWindVanePlugin];
    }

使用WVWKWebView

说明

建议在iOS 9或更高版本再使用WKWebView,iOS 8及之前版本存在较多缺陷。

WVWKWebView使用的是iOS 9.0新加入的WKWebView,使用WebKit内核进行渲染,具有更高的渲染效率和JS执行效率,也支持更多的HTML5特性。有需要的Native业务方可以根据自己的需要,使用WVWKWebView来展示页面。

WindVane iOS版本中,全面优化了对WVWKWebView的支持,通过 [WVURLProtocolServicesetSupportWKURLProtocol:YES]主动开启NSURLProtocol的拦截功能后,可以正常使用预加载功能,持久化Cookie(设置有expires或max-age)也可以正常同步,但POST请求会丢失body,非持久化 Cookie仍是不能同步的。目前仅有XMLHTTPRequest同步POST请求Blob和FormData不支持。

监听页面信息

WindVane提供了页面的基础信息。通过KVO监听WebView title属性和estimatedProgress属性的变化,就可以及时获取页面标题和加载进度的改变,然后客户端自行决定如何显示在界面中。

// 添加 KVO 监听,务必在 WebView 销毁前移除监听。
[_webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNewcontext:nil];

[_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNewcontext:nil];

// 处理 KVO 监听。
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context {
    [super observeValueForKeyPath:keyPathofObject:object change:change context:context];
    if ([keyPathisEqual:@"title"]) {
        // change[NSKeyValueChangeNewKey] 就是新的页面标题。
    } else if ([keyPath isEqual:@"estimatedProgress"]){
        // [change[NSKeyValueChangeNewKey]doubleValue] 就是新的加载进度,范围是 0.0~1.0。
        // 注意加载进度可能在非主线程触发,如果有 UI 操作注意切换线程。
    }
}

- (void)dealloc {
    // 移除KVO监听,这里只是一个示例,根据实际情况不一定要在dealloc中做。
    [_webView removeObserver:selfforKeyPath:@"title"];
    [_webView removeObserver:selfforKeyPath:@"estimatedProgress"];
}

接入灰度SDK

  1. 接入灰度SDK。

        pod 'DynamicConfiguration', '~> 11.0.0'
        pod 'DynamicConfigurationAdaptor', '~> 1.0.0'
  2. 初始化灰度SDK。

    // 灰度初始化
    - (void)initDyConfig
    {
        NSString *appKey = @"xxxxx";  
        NSString * logicIdentifier = [NSString stringWithFormat:@"%@@%@",appKey, [self isDeviceIphone] ? @"iphoneos" : @"iPad"];
        [[DynamicConfigurationAdaptorManager sharedInstance] setUpWithMaxUpateTimesPerDay:10 AndIdentifier:logicIdentifier AndAppkey:appKey];
    }

接入ZCache SDK

1.接入ZCache SDK。

   pod 'ZCache', '~> 11.1.0.0'

2.初始化ZCache SDK。

- (void)initZCache
{
    NSString *appKey = @"xxx";
    NSString *appSecret = @"xxx";
    NSString *version = @"xxx";
    
    [ZCache setupWithAppKey:appKey appSecret:appSecret appVersion:version];
}

(可选)使用JSBridge

JSBridge的Native方法提供方,要像提供普通方法一样提供JSBridge,要求必须满足以下基本约束:

  • 方法调用后,必须返回,任何情况下都要调用callback以将结果返回给JS;可以根据需要返回不同的数据。

  • 方法只能有一个返回值,也就是说callback只允许调用一次,如果有多个数据需要返回给H5,Android请使用标准事件机制,iOS请使用JSBridge context的dispatchEvent方法。

  • 注意做好资源的释放工作,尤其iOS不允许对View或ViewController有强引用。

  1. 注册JSBridge

    EMAS提供了两种注册方案:动态注册和静态注册。

    • 动态注册:无需主动注册给WindVane,使用简单方便。但是要求类名与JSBridge调用时的ClassName相同,且目前仅限WindVane iOS。

    • 静态注册:需要调用WindVane的注册方法,使用操作复杂。不要求特定的类名,会更加灵活。

      总之,只要JSBridge调用的ClassName并没有被占用,那么总是建议使用动态注册的方式。

  2. iOS动态注册JSBridge

    WindVane提供了新版本的用法,在WVBridgeCallbackContext中统一提供了JSBridge需要的所有功能,而且为Weex等非WebView场景也提供了支持。详情请参见下文的新接口介绍

    假设需要实现两个JSBridge:MyJSBridge.firstAPIMyJSBridge.secondAPI,那么JSBridge的ClassName是MyJSBridge,HandlerName分别是firstAPI和secondAPI。

    • 创建一个MyJSBridge类(动态注册要求与JSBridge调用时的ClassName相同),需要确保不会有同名类。

    • 令MyJSBridge类继承自WVDynamicHandler(引入头文件WVDynamicHandler.h)。

    • 实现firstAPI和secondAPI方法,要求方法的签名必须为-/+(void)handlerName:(NSDictionary *)paramswithWVBridgeContext:(id<WVBridgeCallbackContext>)context,其中:

      • 方法可以是静态方法,也可以是动态方法。实例方法会直接调用,实例方法会先创建一个实例,然后在实例上调用。

      • 方法名与JSBridge调用的HandlerName相同,这里为firstAPI和secondAPI。

      • 第一个参数为NSDictionary *,是JS传入的参数对象。

      • 第二个参数为 id<WVBridgeCallbackContext>,是JSBridge的调用上下文。

    • 在方法中实现JSBridge的逻辑,使用[contextcallbackSuccess:RESULT]/[contextcallbackFailure:RET withResult:RESULT]来输出执行成功/失败的结果返回给JSBridge调用方。请保证任何情况下都会调用、且只会调用一次[context callbackXXX]系列方法。

      说明
      • JSBridge总是在主线程调用,如果有耗时操作,请务必自行切换线程。

      • 可能你提供的服务带有多个阶段输出性,请使用[contextdispatchEvent:eventName withParam:param]将结果通过事件的方式输出给JSBridge调用方。

      • 当你的JSBridge逻辑执行完毕,可以主动调用[contextreleaseHandler:self]方法来主动释放内存,否则就只能等到页面销毁的时候才会释放。注意在dealloc中调用是没有意义的,因此此时对象已经被释放了。

      #import <Foundation/Foundation.h>
      #import <WindVane/WindVane.h>
      @interface MyJSBridge : WVDynamicHandler
      @end
      @implementation MyJSBridge
      // 这是一个静态方法,直接调用。
      + (void)firstAPI:(NSDictionary *)params 
      withWVBridgeContext:(id<WVBridgeCallbackContext>)context{
          // 回调中处理业务逻辑
          [context callbackSuccess:nil];
      }
      // 这是一个实例方法,会创建一个新实例,然后再调用。
      
      // API实例
      - (void)secondAPI:(NSDictionary *)params 
          // 回调中处理业务逻辑
          [context callbackSuccess:nil];
      }
      @end

      动态注册的JSBridge,要求类名不能重复。若希望扩展现有ClassName,可以使用JSBridge别名。

常见错误

如果引入WindVane时报如下的错误,那么可以在项目的BuildPhrase中的Link Binary With Libraries中添加 WebKit,并选择Status为Optional。

[MISSING IMAGE:error message | left | 618x118, error message | left | 618x118 ]
[MISSING IMAGE:WebKit framework | left | 479x80, WebKit framework | left | 479x80 ]
  • 使用iOS WebView

    WindVane在iOS平台提供了WVWebView(基于UIWebView)和WVWKWebView(基于WKWebView)的支持,并为两种WebView做了功能和接口的兼容。因此请总是使用UIView*作为WebView的类型,可以兼容WVWebView和WVWKWebView的主要功能。

    另外,请使用#import <WindVane/WindVane.h>来引入WindVane的头文件,无需区分WindVane整包或者分包。您在升级WindVane版本时,请注意检查并修改代码的Warning,尽早修改已废弃的方法。

  • 使用WindVane提供的ViewController

    首先您可以选择使用WindVane提供的含有WebView的WVUIWebViewController,它封装了常用的WebView接口,提供了WVWebView和WVWKWebView切换、状态栏背景兼容、工具栏、错误页、加载框和横屏支持等功能。

    关于UI无关的基础功能信息请参考WVViewController.h,UI相关的功能请参考WVUIWebViewController.h

    要在WVUIWebViewController中切换到WVWKWebView,可以设置useWKWebView属性:

    • WVUseWKWebViewNever表示总是使用WVWebView,是useWKWebView属性的默认值。

    • WVUseWKWebViewAlways表示总是使用WVWKWebView

    • WVUseWKWebViewCustomdecideIsUseWKWebView方法的返回值决定是使用WVWKWebView,还是 WVWebView。由于必须在初始化WebView之前就决定是否切换到WVWKWebView,因此 WVUIWebViewController默认会检查loadUrl中是否包含 _wvUseWKWebView=YES参数,包含的话就切换到WVWKWebView

      #import <WindVane/WindVane.h>
      
      WVUIWebViewController * controller =[[WVUIWebViewController alloc] init];
      controller.loadUrl = @"http://m.taobao.com";
      // 开启 JSBridge,如果需要使用 JSBridge 必须调用。
      controller.openLocalService = YES;
      // [iOS 7 适配] 隐藏导航栏时,为 Status Bar 添加白色背景颜色,按需要设置。
      [controller supportiOS7WithoutStatusBar];
      // 禁用 WebView 的长按事件,按需要设置。
      // controller.openWebKitLongPress = NO;
      [self.navigationController pushViewController:controlleranimated:YES];

WindVane功能说明

  • WindVaneCore

    WindVane核心库,定义了模块间的接口和约束,以及公共工具类,所有模块都必须依赖它。

  • WindVaneBridge

    WindVane JSBridge库,提供了JSBridge的功能,可以在自己的WebView中或者直接脱离WebView使用。

  • WindVaneBasic

    WindVane基础WebView库,提供了WebView相关功能优化和扩展,包括WebView、WKWebView、ViewController、StandardEventModal模块。

  • WindVaneAPI

    WindVane自身提供的一些基础JSBridge API。 需要添加系统库:CoreBluetooth.framework、AddressBookUI.framework、AddressBook.framework、MessageUI.framework、Messages.framework、ContactsUI.framework、Contacts.framework、UserNotifications.framework。

  • WindVaneMonitor

    WindVane埋点支持库,提供了埋点的UT。

  • WindVaneEMASExtension

    EMAS扩展库,主要有URL拦截使用预加载配置和上报Crash,预加载可以让前端在EMAS平台将html、js、css 等资源打包成一个zip包,客户端可以采用启动后下载或者直接预置的方式将zip包解压到本地,使得用户在浏览网页的时候不需要再去下载资源,提升用户体验。

自定义生命周期

如果实现的是实例方法,默认情况下,每次调用都会创建一个实例。该实例会被强引用以保证不会被错误释放,直到WebView被销毁时才会释放。您可以通过以下方法,实现实例生命周期的自定义。

@implementation MyJSBridge
+ (WVBridgeScope)instanceScope {

    return WVBridgeScopeInvocation;
}
@end

WindVane支持四种生命周期:每次调用一个实例(WVBridgeScopeInvocation),每个页面一个实例(WVBridgeScopePage),每个View一个实例(WVBridgeScopeView)和全局唯一实例(WVBridgeScopeStatic)。

对于ScopeInvocation和ScopePage,实例的引用会持续到页面被切换(例如WebView跳转新页面、回退历史记录等)。对于ScopeView,实例的引用会持续到View被销毁。因此在确保当前实例可以被销毁时,建议主动调用 [contextreleaseHandler:self]立刻释放当前实例,以节约内存。ScopeStatic的实例,会一直存在,但也支持通过 [contextreleaseHandler:self] 主动释放。

  • 与View或ViewController交互

    JSBridge中允许与View(包括WebView)或ViewController交互,以实现某些特殊逻辑。或者检查ViewController是否具有特定的类型,以实现只允许在某类ViewController中调用的私有JSBridge。

    不允许对View或ViewController持有强引用,防止出现循环引用导致内存泄露。context已提供view属性和 viewController供实例方法使用,在WebView环境下提供了webViewEnv属性,Weex场景下提供了weexEnv 属性。这些属性会自动设置和更新,您可以直接使用。

  • 发送事件

    在JSBridge中向容器发送事件,请使用[contextdispatchEvent:withParam:],会对当前环境(WebView/Weex)做适配。

    事件机制中提供的方法只能够支持WebView环境。

  • 复杂的JSBridge生命周期管理

    对于一些持续性的JSBridge,如音频播放、动作感应,需要长时间的发送事件。但是在用户跳转到其它Native 页面、跳转到其它H5 WindVane提供了以下生命周期回调方法,可以在JSBridge中实现。

    @implementation MyJSBridge
    /**
    * 重置处理器 - 该方法将会在加载新页面时调用,可以做一些清理工作。
    *
    * @param context WVBridge 被重置时的上下文。
    * @param request 要加载的新页面。
    */
    -(void)resetWithContext:(id<WVBridgeContext>)contextwithNextRequest:(NSURLRequest *)request {
    }
    /**
    
    * 暂停处理器 - 该方法将会在 UIViewControllerviewWillDisappear 时调用,用于降低WVBridge API的性能消耗,例如暂停播放音乐和持续性监听器等。
    * 不会对 WVBridgeScopeStatic 作用域的 WVBridge 调用。
    *
    * @param context WVBridge 被暂停时的上下文。
    */
    -(void)pauseWithContext:(id<WVBridgeContext>)context {
    }
    /**
    
    * 恢复处理器 - 该方法将会在 UIViewControllerviewWillAppear 时调用,用于恢复 WVBridge API 的性能,例如恢复播放音乐和持续性监听器等。
    * 不会对 WVBridgeScopeStatic 作用域的 WVBridge 调用。
    *
    * @param context WVBridge 被恢复时的上下文。
    */
    -(void)resumeWithContext:(id<WVBridgeContext>)context {
    }
    @end

    如果JSBridge需要在切换到新页面后自动清理,需要实现resetWithContext:withNextRequest:;如果需要在当前 UIViewController被其它Native界面覆盖时暂停和恢复,需要实现pauseWithContext: resumeWithContex:。一般建议与WVBridgeScopeView同时使用。

    如果需要在应用切换前后台时做特殊工作,可以自行注册UIApplicationDidBecomeActiveNotificationUIApplicationWillResignActiveNotification这两个通知。

  • 新接口介绍

    在新版本JSBridge接口,将所有功能收拢到了统一的id<WVBridgeCallbackContext>中,一切功能都可以通过context来实现。具体包括:

    • 获取环境信息,基本信息有来源URL referrer,view和viewController,以及当前的环境 envUIView<WVWebViewBasicProtocol> *WeexSDKInstance *

    • 发送事件,提供了dispatchEvent:withParam: 方法。

    • 释放实例,提供了releaseHandler: 方法。

    • 回调,提供了callbackSuccess: callbackFailure:withResult:方法,以及一系列失败回调的快捷方法。

    • 所有JSBridge的方法参数全部统一为NSDictioanry* paramsid<WVBridgeCallbackContext> context,无论是动态注册,还是各类静态注册的方法。

支持懒加载的动态库

一些客户端为了提高应用打开速度,对动态库做了懒加载处理,这样可以将动态库的加载延迟到使用时,避免影响应用启动耗时。

如果动态库中提供了动态注册JSBridge,那么在动态库被加载之前,是找不到对应的类的,也无法正常调用。因此我们懒加载的动态库做了特别的支持,允许动态库通过plist 配置动态JSBridge的类名,以便WindVane在需要使用JSBridge时主动将动态库加载进来。

解决方案是在动态库的framework根目录,提供一个命名为XXX_bundle.plist的文件,其中的XXX部分可以任意命名,甚至同一个framework包含多个符合此规则的plist也可以。在plist中添加名为windvane_bridge_list的数组,并在数组中添加需要配置的动态JSBridge类名,多个plist的配置会自动合并。示例如下:

[MISSING IMAGE:Dynamic Framework Config | left | 600x374, Dynamic Framework Config | left |600x374 ]

请确保动态库全部位于客户端的Frameworks目录,如果不同动态库之间的映射关系存在覆盖,动态库会在JSBridge被首次使用时,打出日志 'A' 注册的WVBridge 'XXX' 被 'B' 覆盖了,此外,在WindVane的DEBUG模式下还会弹出Alert提示。

iOS静态注册JSBridge

WindVane iOS允许将JSBridge注册到全局,也可以注册到特定WebView。前者可以在任意WebView中调用,而后者只能在注册的WebView中使用,适合需要较严格的权限控制的JSBridge。 但是注册到全局的JSBridge,也可以通过对ViewController 的类型或属性进行校验,以达到部分权限的控制,因此如无特别的必要,请总是将JSBridge注册到全局,会有更少的内存消耗。

  • 将JSBridge注册到全局

    #import <WindVane/WindVane.h>
    // JSBridge 调用的 Block。
    WVBridgeHandler handler = ^(NSDictionary *params, id<WVBridgeCallbackContext> context) {
        [context callbackSuccess:nil];
    };
    // 注册JSBridge到全局,特别注意这里的JSBridge 名称合并写作@"className.handlerName" 格式。
    WVBridgeRegisterHandler(@"className.handlerName",handler);
  • 将JSBridge注册到特定WebView

    这样注册的JSBridge,只能在注册到的WebView中使用className和handlerName调用。

    #import <WindVane/WindVane.h>
    // JSBridge 调用的 Block
    WVBridgeHandler handler = ^(NSDictionary *params, id<WVBridgeCallbackContext> context) {
        [context callbackSuccess:nil];
    };
    // 注册 JSBridge 到指定 WebView,特别注意这里的 JSBridge 名称合并写作
    @"className.handlerName" 格式。
    [webview registerHandler:@"className.handlerName" withBlock:handler];
    // 注册 JSBridge到指定ViewController中的WebView,特别注意这里的JSBridge名称合并写作 @"className.handlerName" 格式。
    [wvViewController registerHandler:@"className.handlerName" withBlock:handler];

    静态注册的JSBridge,不支持复杂的生命周期管理。如果需要实现复杂的JSBridge,请动态注册JSBridge。

    静态注册的JSBridge,若className和handlerName都相同,那么后注册的会覆盖先注册的。同时也会覆盖同名的动态注册方法。

JSBridge别名

WindVane提供了JSBridge的别名服务,可以用来对现有ClassName的JSBridge进行扩展或覆盖,也可以对JSBridge的升级、更新、改名和冲突提供解决方案。

允许将原始的JSBridge className.handlerName,映射到新的别名aliasClassName.aliasHandlerName,您既可以使用旧的className.handlerName来访问,也可以使用新的aliasClassName.aliasHandlerName来访问。

WindVane的别名服务,是首先将别名解析为原始名称,然后使用原始名称来查找 JSBridge;不要将别名指向其它别名,可能导致无法正确找到JSBridge。

iOS注册全局别名:全局别名必须与全局JSBridge配合使用。

#import <WindVane/WindVane.h>
// 注册 JSBridge 别名到全局。
NSDictionary * alias = @{

    @"类别名.方法别名": @"类名.方法名",
    @"aliasClassName.aliasHandlerName":@"className.handlerName"
};
WVBridgeRegisterAlias(alias);

JSBridge全局鉴权

WindVane提供了JSBridge的全局鉴权接口,供实现App级别的JSBridge API鉴权。该鉴权层切入到JSBridge的调用逻辑中,可以由客户端统一自定义鉴权逻辑。

对于单个JSBridge的鉴权,请在该JSBridge的实现中自行实现。

#import <WindVane/WindVane.h>
// 实现 JSBridge 鉴权方法。
@interface MyJSBridgeCheckerHandler : NSObject<WVBridgeCheckerProtocol>
@end
@implementation MyJSBridgeCheckerHandler
/**

检查指定 WVBridge 是否具有执行权限。
* 总是在后台线程调用。
*
* @param apiName WVBridge 的名称,格式为 "类名.方法名"。
* @param paramsWVBridge 的调用参数。
* @param context WVBridge 的执行上下文。
*
* @return 权限检查结果。
*/
- (WVBridgePermission*)checkPermission:(NSString *)apiName withParams:(NSDictionary *)paramswithContext:(id<WVBridgeContext>)context {
    return [WVBridgePermissionpermissionNotSure];

}
@end

// 注册鉴权处理器。

[WVBridgeChecker registerChecker:[[MyJSBridgeCheckerHandler alloc]init]];

在Native中使用JSBridge

WindVane iOS中,支持在Native中调用JSBridge。现在提供有两种用法:

  • 简单用法

    这里适合一些简单场景下,Native调用与UI无关的JSBridge。直接调用[WVBridge callHandler:withParams:withCallback:]方法,传入以下参数:

    • name: 要执行的JSBridge名称,格式为@"类名.方法名"。

    • params: 要执行的JSBridge参数,与JS使用方式保持一致 ,对象用NSDictionary代替,数组用NSArray代替)。

    • callback: 此次JSBridge调用的回调,可能在任意线程调用。

  • 复杂用法

    这里适合Native调用全功能的JSBridge,可以用于在自己的容器中完整接入JSBridge。

    • 实现WVBridgeDelegate协议,供JSBridge回调数据给Native。

    • 实例化自己的WVBridge实例,传入env和上面实现的delegate。

    • 设置 WVBridge 实例的view和viewController属性,为JSBridgeAPI提供环境信息。其它属性可以根据需要设置:

      • opageId:当前页面的ID,变化后前一页面未调用的JSBridge会全部失效,避免影响到当前页面。

      • oopenPermissionCheck:启用白名单校验,只允许符合WindVane domain 配置中的Ali域名白名单的 URL 调用JSBridge,其它URL的调用都会被拒绝。

    • 调用callHandlerWithRequest:callHandlerWithURL: callHandler:withParams:withReqId:方法之一,就会调用实际的JSBridge,JSBridge的回调、事件都会通过delegate返回回来。

  • 标准事件机制

    WindVane的标准事件机制,提供了Native和H5之间互发事件的标准通讯接口,便于各业务场景下的基于统一的事件模型来通讯。

  • Native向H5发送事件

    WindVane提供了WVStandardEventCenter 类,供Native向H5发送事件:

    在事件参数中,WebView是要发送事件的目标WebView,eventName是事件的名称(字符串),eventData是事件的数据(iOS是NSDictionary*,Android是一个JSON Object格式的String)。在iOS平台的JSBridge中,不建议使用这里的方法来发送事件,而是使用JSBridge context的dispatchEvent方法来发送事件,对多种容器(WebView/Weex)提供了兼容。

    #import <WindVane-Basic/WVStandardEventCenter.h>
    // 向指定 WebView 发送事件。
    [WVStandardEventCenter postNotificationToJS:eventName withEventData:eventData withWebView:webView];
    // 向所有 WebView 发送事件,请谨慎使用。
    [WVStandardEventCenter postNotificationToJS:eventName withEventData:eventData];

    H5用法:

    document.addEventListener('eventName', function(data) {
    // 这里要注意,Native 传递过来的事件参数是在data的param属性中。
    alert(data.param);
    }, false);
  • H5向Native发送事件

    H5用法:使用JSBridge来发送事件,注意引入windvane.js,详情可以参考如下示例。

    WVStandardEventCenter.postNotificationToNative:
    var params = {
        event: 'eventName',
        param: {
            // 事件要传递的数据。
        }
    };
    
    window.WindVane.call('WVStandardEventCenter','postNotificationToNative',params, 
    function(e) {
        alert('success');
    }, function(e) {
        alert('failure: ' + JSON.stringify(e));
    });
    

    iOS用法:使用标准的消息中心监听事件。

    [[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(myEventListener) name:eventName object:nil]
    - (void)myEventListener:(NSNotification*)notification {
    
    // 事件参数可以从 notification.userInfo 中获取。
    }
  • 本页导读 (0)
文档反馈