iOS 快速集成

更新时间:2018-09-07 16:40:01

EMAS iOS SDK快速集成

本文档为EMAS iOS SDK快速集成手册。SDK整体功能包括几部分:高可用、WEEX和热修复。

1 接入准备

1.1 环境准备

  • 本机正确安装好Ruby、Gitlab、CocoaPods等开发环境,保证功能可用。

1.1.1 检查 RubyGems 源

如果之前安装过 RubyGems 并且使用了 taobao.org 提供的 Ruby 源,需要将其替换为 ruby-china 提供的 Ruby 源,否则工具安装过程中可能会出现错误,因为 taobao.org 已不再维护 RubyGems 源,详情可参考 https://gems.ruby-china.org/

  • 检查本地的 Ruby 源

    1. gem source
  • 去除使用的 taobao 源(如果存在)

    1. sudo gem source --remove https://ruby.taobao.org/
  • 使用下面的指令替换 gem 源

    1. sudo gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
  • 检查确保只有 gems.ruby-china.org

    1. 命令行敲入如下命令: gem sources -l
    2. 结果显示如下内容即可:
    3. *** CURRENT SOURCES ***
    4. http://gems.ruby-china.org/

1.1.2 升级 RubyGems

RubyGems 是 Ruby 的一个包管理框架, 提供了分发 Ruby 程序和函式库的标准格式 gem,旨在方便地管理安装 gem 过程中需要的工具。Mac 系统本身支持 Ruby,需要对 RubyGems 进行检查更新。

  • 升级RubyGems

    1. sudo gem update
  • 升级完成之后检查 RubyGems 的版本,建议使用 RubyGems 2.6.10 或更高版本。

    1. gem -v

    升级 RubyGems 有时会因为依赖的缺失造成升级失败,这时可执行下面的命令安装更新 Homebrew 相关工具来解决:

  • 检查 HomeBrew 版本号,建议使用 HomeBrew 1.1.11 或更高版本
  1. brew --version
  • 安装 Homebrew(执行 brew 如果命令不存在则表示未安装 Homebrew)
  1. ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 更新 Homebrew 相关工具(如果是 Mac 10.12 之后的系统版本,执行之前需要先执行 sudo chown -R $(whoami) /usr/local)
  1. brew update
  • 注意更新完 Homebrew 相关工具之后需要回到前面继续升级 RubyGems

安装 Homebrew 时,有时会因为网络等问题安装失败,这时只需要重新执行命令即可,在安装更新 Homebrew 相关工具之后,升级 RubyGems 还是出现问题,可参考 https://rubygems.org/pages/download 以及 FAQ 中的说明解决。

1.1.3 配置Gitlab

1.1.4 安装CocoaPods环境

  • 安装CocoaPods,指定1.2.0版本
  1. sudo gem install cocoapods -v 1.2.0

1.2 集成准备

  • SDK集成方式包括两部分:手动集成部分(仅热修复产品)和Pods依赖部分,两者需要结合共同使用。

1.3 仓库账号

  • 请先联系工作人员提供Gitlab、CocoaPods等账号,这样才能拉取到EMAS的DemoApp和相关功能的SDK。

1.4 下载

  • 我们提供了一个简单的demo,包含SDK初始化、SDK功能使用供大家参考。请联系工作人员提供Gitlab账号。

2 应用信息和SDK配置信息

2.1 应用基本信息

集成前需要获取应用的信息和SDK相关配置信息。SDK中有的接口需要依赖这些信息才能正常的工作。

应用基本信息:AppKey和AppSecret。

比如:

  • AppKey = 10000040
  • AppSecret = c66e5b00ff97809daac7ad60b2eebf20

2.2 SDK配置信息

  • ACCS请求域名:TBAccsManager接口的host。比如host = emaspoc-acs.emas-ha.cn

  • 高可用服务公钥:AliHASecurity接口的initWithRSAPublicKey。有内部公钥,若有特殊说明需要替换需要调用该接口替换。

  • 高可用服务域名:TBRestConfiguration接口的dataUploadHost。比如dataUploadHost = emaspoc-adash.emas-ha.cn

  • 高可用服务请求协议:dataUploadScheme。默认使用https协议,若需要降级抓请求,可以设置为http

  • 高可用OSSBucketName:AliHAAdapter头文件的configOSS接口,OSS Bucket唯一标识。比如OSS bucketName = emas-ha-remote-log-poc

  • 高可用服务域名:AliHAAdapter头文件的setupRemoteDebugRPCChannel:scheme接口,配置TLOG上报地址,比如 domain= emaspoc-adash.emas-ha.cn,scheme=https,默认使用https协议,若需要降级抓请求,scheme可以设置为http

  • 高可用获取时间戳域名:UTAnalytics.h头文件的setTimestampHost:scheme:接口,值与MTOP请求域名一致。scheme为请求该服务的协议,可以是https或者http。

  • 高可用ACCSChannel域名和serverID:AliHAAdapter.h头文件的setupAccsChannel:serviceId:接口,其中host=ACCS请求域名,serverID目前固定为emas-ha,如有变更,请更新

  • 高可用app渠道号:AliHAAdapter接口的channel,渠道号组成规则(渠道ID@应用英文名_应用os_版本号),比如channel = @”1001@Test_iOS_1.0.0”。

  • 预加载zip包下载前缀地址:ZCache接口的packageZipPrefix。比如packageZipPrefix = http://publish-poc.emas-ha.cn/eweex/

  • MTOP请求域名和渠道ID: TBSDKConfiguration的wapAPIURL和wapTTID,其中wapTTID也是app渠道号,同channel即可。wapAPIURL为mtop请求域名,比如wapAPIURL = emaspoc-aserver.emas-ha.cn。

  • 热修复appId:AlicloudHotFixServiceEmas接口的appId,这里的appId就是AppKey。

  • 热修复server_url:热修复服务器地址,AlicloudHotFixServiceEmas接口的setServerURL方法。

3 开始接入

3.1 SDK初始化方法

初始化方法调用应该尽可能的早,尽量在-[AppDelegate application:didFinishLaunchingWithOptions:]或者viewDidLoad的最开始进行SDK初始化操作,初始化之前不能用到其他自定义类,否则极有可能导致崩溃。

4 接入高可用

4.1 指定Pod源

  1. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs.git'
  2. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs-thirdpart.git'

4.2 添加依赖

  1. pod 'AliHAAdapter4poc', '10.0.5.2'
  2. pod 'TRemoteDebugger', '10.0.3'
  3. pod 'UserTrack', '6.3.5.100005-poc'
  4. pod 'Reachability', '3.2'
  5. pod 'FMDB', '2.7.2'
  6. pod 'ZipArchive', '~> 1.4.0'
  7. pod 'NetworkSDK', '10.0.4.2'
  8. pod 'TBAccsSDK', '10.0.7'
  9. pod 'tnet', '10.2.0'

4.3 高可用相关方法

  1. UTAnalytics.h头文件
  2. /**
  3. 获取UT实例
  4. */
  5. +(UTAnalytics *)getInstance;
  6. /**
  7. 初始化appKey和appSecret
  8. @param appKey 应用appKey
  9. @param secret 应用secret
  10. */
  11. - (BOOL)setAppKey:(NSString *)appKey secret:(NSString *)secret;
  12. /**
  13. * 设置渠道号
  14. */
  15. -(void) setChannel:(NSString *) pChannel;
  16. /**
  17. * 设置版本号
  18. */
  19. -(void) setAppVersion:(NSString *) pAppVersion;
  20. /**
  21. * 设置拉取时间戳域名和指定请求的协议,scheme可以为http或者https
  22. */
  23. - (void)setTimestampHost:(NSString *)host scheme:(NSString *)scheme
  24. AliHAAdapter.h头文件
  25. /**
  26. * initialize AliHA
  27. * @param appKey appkey
  28. * @param appVersion app版本
  29. * @param channel 渠道ID
  30. * @param plugins custom plugins, and default plugins(crash, performance) will be registered if plugins is nil
  31. */
  32. + (void)initWithAppKey:(NSString *)appKey
  33. appVersion:(NSString *)appVersion
  34. channel:(NSString *)channel
  35. plugins:(NSArray<id<AliHAPluginProtocol>> *) plugins
  36. nick:(NSString *)nick
  37. /**
  38. * config oss with end poi
  39. * OSS Bucket唯一标识
  40. */
  41. + (void)configOSS:(NSString *)ossBucketName;
  42. TBRestSendService.h头文件
  43. /**
  44. * 配置数据上报地址
  45. */
  46. - (BOOL)configBasicParamWithTBConfiguration:(TBRestConfiguration*)config;
  47. /**
  48. * 配置ACCS通道,domain为accsDomain,serviceID无特殊说明请传"emas-ha"
  49. */
  50. + (void)setupAccsChannel:(NSString *)domain serviceId:(NSString *)serviceId
  51. /**
  52. * 配置TLOG上报地址
  53. */
  54. + (void)setupRemoteDebugRPCChannel:(NSString *)host scheme:(NSString *)scheme
  55. AliHASecurity.h头文件
  56. /**
  57. * 配置高可用的公钥
  58. */
  59. - (void)initWithRSAPublicKey:(NSString *)key
  60. NWNetworkConfiguration.h头文件
  61. /**
  62. * 设置网络环境。
  63. * @param env 三种环境:release, releaseDebug, daily
  64. */
  65. + (void)setEnvironment:(NetworkEnv)env;
  66. /**
  67. * 设置appKey。
  68. */
  69. + (void)setAppkey:(NSString *)appKey;
  70. /**
  71. * 设置appSecret。
  72. */
  73. + (void)setAppSecret:(NSString *)appSecret;
  74. /**
  75. * 设置使用安全保镖,默认为YES
  76. */
  77. + (void) setIsUseSecurityGuard:(BOOL)use;
  78. /**
  79. * 设置使用AMDC,默认为YES
  80. */
  81. + (void) setIsEnableAMDC:(BOOL)use;
  82. NetworkDemote.h头文件
  83. /**
  84. * 设置是否接管,默认为YES
  85. */
  86. + (void)setCanInitWithRequest:(BOOL)use;
  87. TBAccsManager.h头文件
  88. /**
  89. 获取accs实例
  90. */
  91. /**
  92. * 获取长连接操作对象,操作单元的时候调用此方法
  93. *
  94. * @param host ACCS请求域名,参考上文的SDK配置信息正常设置即可
  95. */
  96. + (TBAccsManager *)accsManagerByHost:(nonnull NSString *)host;
  97. /**
  98. * 设置是否打开localdns获取策略,默认为NO
  99. */
  100. + (void)setSupportLocalDNS:(BOOL)support;
  101. /**
  102. * 设置使用的公钥
  103. */
  104. + (void)slightSslPublicKeySeq:(int)key;
  105. /**
  106. * 启动ACCS实例
  107. */
  108. - (void)startAccs;
  109. **
  110. * 绑定app
  111. *
  112. * @param appleToken 苹果APNS所需要deviceToken,可以为空
  113. * @param resultsBlock 请求响应回调
  114. */
  115. - (void)bindAppWithAppleToken:(NSData *)appleToken
  116. callBack:(TBAccsManagerResponseBlock)callBack;
  • AppKey、AppSecret、channel、host、ossBucketName信息,参考2.1章节正常设置即可。

4.4 高可用初始化示例

  • 由于高可用依赖通用库和ACCS,所以初始化高可用前,要先初始化通用库和ACCS.
  • 网关初始化顺序:通用库-> ACCS -> 高可用

1) 通用库初始化参考

2) ACCS初始化参考

3)高可用初始化,以下示例代码为了方便把所有依赖初始化都列出

  1. #import <UT/UTAnalytics.h>
  2. #import <UT/AppMonitor.h>
  3. #import <NetworkSDK/NetworkCore/NWNetworkConfiguration.h>
  4. #import <NetworkSDK/NetworkCore/NetworkDemote.h>
  5. #import <NetworkSDK/NetworkCore/NWuserLoger.h>
  6. #import <TBAccsSDK/TBAccsManager.h>
  7. #import <AliHAAdapter4poc/AliHAAdapter.h>
  8. #import <AliHASecurity/AliHASecurity.h>
  9. #import <TRemoteDebugger/TRDManagerService.h>
  10. #import <TBRest/TBRestSendService.h>
  11. #import <TBCrashReporter/TBCrashReporterMonitor.h>
  12. // UT初始化部分
  13. [[UTAnalytics getInstance] turnOffCrashHandler];
  14. [[UTAnalytics getInstance] turnOnDebug]; // 打开调试日志
  15. //scheme指定了埋点上报组件的请求协议,可以是https或者http
  16. [[UTAnalytics getInstance] setTimestampHost:timestampHost scheme:scheme];
  17. [[UTAnalytics getInstance] setAppKey:AppKey secret:AppSecret];
  18. [[UTAnalytics getInstance] setChannel:channel];
  19. [[UTAnalytics getInstance] setAppVersion:appversion];
  20. [AppMonitor disableSample]; // 调试使用,上报不采样,建议正式发布版本不要这么做
  21. // 网络库初始化部分
  22. [NWNetworkConfiguration setEnvironment:release];
  23. NWNetworkConfiguration *configuration = [NWNetworkConfiguration shareInstance];
  24. [configuration setIsUseSecurityGuard:NO];
  25. [configuration setAppkey:AppKey];
  26. [configuration setAppSecret:AppSecret];
  27. [configuration setIsEnableAMDC:NO];
  28. [NetworkDemote shareInstance].canInitWithRequest = NO;
  29. setNWLogLevel(NET_LOG_DEBUG); // 打开调试日志
  30. // ACCS初始化部分
  31. void tbAccsSDKSwitchLog(BOOL logCtr);
  32. tbAccsSDKSwitchLog(YES); // 打开调试日志
  33. TBAccsManager *accsManager = [TBAccsManager accsManagerByHost:ACCSDomain];
  34. [accsManager setSupportLocalDNS:YES];
  35. accsManager.slightSslPublicKeySeq = ACCS_PUBKEY_PSEQ_EMAS;
  36. [accsManager startAccs];
  37. [accsManager bindAppWithAppleToken: nil
  38. callBack:^(NSError *error, NSDictionary *resultsDict) {
  39. if (error) {
  40. NSLog(@"\n\n绑定App出错了 %@\n\n", error);
  41. }
  42. else {
  43. NSLog(@"\n\n绑定App成功了\n\n");
  44. }
  45. }];
  46. // 高可用初始化部分
  47. // 如果需要重公钥,请一定要放到初始化前!!!
  48. NSString *rasPublicKey = xxx
  49. if (rasPublicKey.length > 0)
  50. {
  51. [[AliHASecurity sharedInstance] initWithRSAPublicKey:rasPublicKey];
  52. }
  53. [AliHAAdapter initWithAppKey:AppKey appVersion:@"1.0.0" channel:CHANNELID plugins:nil nick:@"emas-ha"];
  54. [AliHAAdapter configOSS:ossBucketName];
  55. [AliHAAdapter setupAccsChannel:ACCSDomain serviceId:@"emas-ha"];
  56. [AliHAAdapter setupRemoteDebugRPCChannel:HAUniversalHost scheme:kHTTPSProtocol]; //scheme指定了埋点上报组件的请求协议,可以是https或者http
  57. TBRestConfiguration *restConfiguration = [[TBRestConfiguration alloc] init];
  58. restConfiguration.appkey = appKey];
  59. restConfiguration.appVersion = appversion;
  60. restConfiguration.channel = ChannelID;
  61. restConfiguration.usernick = usernick;
  62. restConfiguration.dataUploadHost = UniversalHost;
  63. //默认请求协议为https,若需要降级到HTTP协议下抓包,可以指定dataUploadScheme为http
  64. //restConfiguration.dataUploadScheme = @"http";
  65. [[TBRestSendService shareInstance] configBasicParamWithTBConfiguration:restConfiguration];

5 接入EMASWeex

EMASWeex 旨在为EMAS使用WeexSDK的用户提供WeexSDK的封装,方便用户更快接入WeexSDK

5.1 EMASWeex版本及相关依赖

5.1.1 指定仓库:

  1. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs.git'
  2. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs-thirdpart.git'

5.1.2 添加依赖

  1. pod 'UserTrack', '6.3.5.100005-poc'
  2. pod 'NetworkSDK', '10.0.4.2'
  3. pod 'tnet', '10.2.0'
  4. pod 'TBAccsSDK', '10.0.7'
  5. pod 'MtopSDK', '10.0.6'
  6. pod 'mtopext/MtopCore', '10.0.6'
  7. pod 'AliHAAdapter4poc', '10.0.5.2'
  8. pod 'WeexSDK', '0.17.0.1-EMAS'
  9. pod 'ZCache', '10.0.3'
  10. pod 'SDWebImage', '3.7.5'
  11. pod 'EMASWeex', '1.1.0'

5.2 EMASWeex初始化

5.2.1 SDKEngine配置

可继承EMASWXSDKEngine,并直接调用initWXSDKEnviroment即可。`EMASWXSDKEngine内部注册了WXAppMonitorProtocol WXImgLoaderProtocol WXResourceRequestHandler WXJSExceptionProtocol的默认实现handler,业务方可直接使用,也可以自己实现协议,覆盖默认handler,默认handler说明见下方。EMASWXSDKEngine还接管了app crash,crash产生,会自动上报EMAS平台。

  1. //.h
  2. @interface EMASWXSubSDKEngine : EMASWXSDKEngine
  3. + (void)setup;
  4. @end
  5. //.m
  6. @implementation EMASWXSubSDKEngine
  7. + (void)setup {
  8. static dispatch_once_t onceToken;
  9. dispatch_once(&onceToken, ^{
  10. [self initWXSDKEnviroment];
  11. });
  12. }
  13. + (void)appConfig {
  14. [super appConfig];
  15. [WXAppConfiguration setAppGroup:@"TestApp"];
  16. [WXAppConfiguration setAppName:@"EMASDemo"];
  17. [WXAppConfiguration setAppVersion:[[EMASService shareInstance] getAppVersion]];
  18. }
  19. + (void)registerHandler {
  20. [super registerHandler];
  21. [self registerHandler:[EMASWXNavigationImpl new] withProtocol:@protocol(WXNavigationProtocol)];
  22. }
  23. + (void)registerModule {
  24. [super registerModule];
  25. }
  26. @end

5.2.2 业务方初始化

作为基础中间件使用方尽量早的初始化EMASWeex,建议在程序启动后在Appdelegate中的didFinishLaunchingWithOptions回调中完成初始化工作。

EMASWXSDKEngine初始化前需要先初始化基础库、高可用、网关、远程配置、ZCache,具体可见EMAS iOS SDK快速集成

  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  2. self.window.backgroundColor = [UIColor whiteColor];
  3. // 1. 先初始化基础库
  4. [self initCommonConfig];
  5. // 2. 初始化高可用,高可用依赖基础库和ACCS,因此高可用的初始化顺序为,基础库->ACCS->高可用
  6. [self initAccsConfig];
  7. [self initHAConfig];
  8. // 3. 初始化Weex,Weex依赖基础库、网关和高可用,因此Weex的初始化顺序为,基础库->高可用->网关->远程配置->ZCache->Weex
  9. //[self initRemoteConfig];
  10. [self initMtopConfig];
  11. [self initZCacheConfig];
  12. // 4. 初始化PUSH
  13. [self initPushConfig];
  14. [EMASWXSubSDKEngine setup];
  15. [self initDyConfig];
  16. return YES;
  17. }

5.3 通用渲染层

WeexSDK渲染相关的逻辑统一放在EMASWXViewController中,该ViewController属于渲染容器,还需要业务方提供宿主容器EMASHostViewControllerEMASWXViewController通过addChildViewController方法添加到宿主容器中,使用这种方式,可以将渲染容器和宿主容器解耦,同时不失宿主容器自身的平台特性。

业务方可以继承EMASWXViewController,对渲染过程自定义:

  1. //.h
  2. @interface EMASWXRenderViewController : EMASWXViewController
  3. @end
  4. //.m
  5. @implementation EMASWXRenderViewController
  6. //获取宿主容器的导航控制器。由于当前渲染容器是通过addChildViewController的方式添加到宿主容器中,因此所属的导航控制器应该是通过宿主容器获取。
  7. - (UIViewController *)wxNavigationController {
  8. if (self.parentVC) {
  9. return self.parentVC.navigationController;
  10. }
  11. return nil;
  12. }
  13. //获取渲染容器包含的子视图控制器。例如,web对应的component,它会生成webviewController,并通过addChileViewController的方式添加到渲染容器中。
  14. - (NSMutableArray *)wxChildViewControllers {
  15. return (NSMutableArray *)self.childViewControllers;
  16. }
  17. //在渲染容器中添加特定的子视图控制器。
  18. - (void)wxAddChildViewController:(UIViewController *)viewController {
  19. [self addChildViewController:viewController];
  20. }
  21. //在渲染容器中移除特定的子视图控制器。
  22. - (void)wxRemoveChildViewController:(UIViewController *)viewController {
  23. [viewController removeFromParentViewController];
  24. }
  25. //判断宿主容器导航栏是否隐藏
  26. - (BOOL)wxNavbarIsHidden {
  27. EMASWXViewController *parentVC = (EMASWXViewController *)self.parentVC;
  28. if (parentVC && parentVC.navigationController.navigationBarHidden) {
  29. return YES;
  30. }
  31. return NO;
  32. }
  33. //自定义页面加载的indicatorView,并显示在view中。
  34. - (void)wxShowPageLoadingIndicator:(UIView *)view {
  35. [view addSubview:self.pageLoadingIndicator];
  36. [self.pageLoadingIndicator startAnimating];}
  37. //隐藏indicatorView
  38. - (void)wxHidePageLoadingIndicator {
  39. [self.pageLoadingIndicator stopAnimating];
  40. [self.pageLoadingIndicator removeFromSuperview];
  41. }
  42. - (UIActivityIndicatorView *)pageLoadingIndicator {
  43. if (_pageLoadingIndicator == nil) {
  44. self.pageLoadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake((self.view.frame.size.width - 40)/2, (self.view.frame.size.height - 40)/2, 40, 40)];
  45. [self.pageLoadingIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
  46. }
  47. return _pageLoadingIndicator;
  48. }
  49. - (void)wxInstanceRenderOnCreate {
  50. // Weex渲染容器在实渲染中判断当前实例是否可以被复用
  51. }
  52. - (void)wxInstanceRenderOnFail:(NSError *)error {
  53. // Weex实例渲染失败回调,返回错误信息
  54. }
  55. - (void)wxInstanceRenderOnFinish {
  56. // Weex实例渲染完成回调
  57. }
  58. - (void)wxJSBundleDownloadOnFinish:(WXResourceResponse *)response request:(WXResourceRequest *)request data:(NSData *)data error:(NSError *)error {
  59. // JS Bundle下载回调
  60. }
  61. @end

业务方提供宿主容器EMASHostViewController ,继承自UIViewController或者UINavigationController

  1. //.h
  2. //宿主容器
  3. @interface EMASHostViewController : UIViewController <EMASWXViewControllerProtocol,SRWebSocketDelegate>
  4. @property (nonatomic, strong) SRWebSocket *hotReloadSocket;
  5. @property (nonatomic, copy) NSString *source;
  6. @property(nonatomic, strong) EMASWXRenderViewController *wxViewController;
  7. - (id)initWithNavigatorURL:(NSURL *)URL;
  8. @end
  9. //.m
  10. @interface EMASHostViewController()
  11. @property (nonatomic, copy) NSString *resourceUrlString;
  12. @property (nonatomic, strong) UIWebView *webView;
  13. @end
  14. @implementation EMASHostViewController
  15. - (void)dealloc {
  16. if (self.wxViewController) {
  17. [self.wxViewController removeFromParentViewController];
  18. }
  19. }
  20. - (instancetype)init {
  21. self = [super init];
  22. if (self) {
  23. self = [self initWithNavigatorURL:[NSURL URLWithString:@""]];
  24. }
  25. return self;
  26. }
  27. - (instancetype)initWithNavigatorURL:(NSURL *)URL {
  28. self = [super init];
  29. if (self) {
  30. self.resourceUrlString = URL.absoluteString;
  31. NSString * urlString = self.resourceUrlString;//[[DynamicConfigurationManager sharedInstance] redirectUrl:[URL absoluteString]];
  32. self.wxViewController = [[EMASWXRenderViewController alloc] initWithNavigatorURL:[NSURL URLWithString:urlString] withCustomOptions:@{@"bundleUrl":urlString} withInitData:nil withViewController:self];
  33. //渲染容器的外部代理。
  34. self.wxViewController.delegate = self;
  35. }
  36. return self;
  37. }
  38. - (void)viewDidLoad {
  39. [super viewDidLoad];
  40. [self setupNaviBar];
  41. //务必设置这个属性,它与导航栏隐藏属性相关。
  42. self.edgesForExtendedLayout = UIRectEdgeNone;
  43. //在宿主容器中添加渲染容器和视图。
  44. [self.view addSubview:self.wxViewController.view];
  45. [self addChildViewController:self.wxViewController];
  46. self.view.backgroundColor = [UIColor whiteColor];
  47. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationRefreshInstance:) name:@"RefreshInstance" object:nil];
  48. }
  49. # pragma mark WXViewController Delegate
  50. //内存报警时销毁非当前实例, 是否销毁通过配置下发。
  51. - (void)wxDidReceiveMemoryWarning {
  52. id weex_memory_warning_destroy = @"1";
  53. if (weex_memory_warning_destroy && [@"1" isEqualToString:weex_memory_warning_destroy]) {
  54. if (self.wxViewController.isViewLoaded && [self.view window] == nil ) {
  55. [self.wxViewController.instance destroyInstance];
  56. self.wxViewController.instance = nil;
  57. }
  58. }
  59. }
  60. - (void)wxFinishCreateInstance {
  61. //Weex Instance创建成功
  62. [self.webView removeFromSuperview];
  63. }
  64. - (void)wxFailCreateInstance:(NSError *)error {
  65. //Weex Instance创建失败
  66. }
  67. - (void)wxFinishRenderInstance {
  68. //Weex Instance渲染完成
  69. }
  70. - (void)wxDegradeToH5:(NSString *)url
  71. {
  72. [self.wxViewController.instance destroyInstance];
  73. [self.wxViewController.weexView removeFromSuperview];
  74. [self.webView removeFromSuperview];
  75. self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
  76. [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
  77. [self.view addSubview:self.webView];
  78. }
  79. #pragma mark - websocket
  80. - (void)webSocketDidOpen:(SRWebSocket *)webSocket
  81. {
  82. }
  83. - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
  84. {
  85. if ([@"refresh" isEqualToString:message]) {
  86. [self.wxViewController refreshWeex];
  87. }
  88. }
  89. - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
  90. {
  91. }
  92. #pragma mark - notification
  93. - (void)notificationRefreshInstance:(NSNotification *)notification {
  94. [self.wxViewController refreshWeex];
  95. }
  96. @end

5.4 protocol默认实现handler说明

protocol Note
WXAppMonitorProtocol 使用了UserTrack库,用于埋点
WXImgLoaderProtocol 使用了 SDWebImage库,用于图片下载
WXResourceRequestHandler 基于 NSURLSession ,处理网络请求,缓存使用了ZCache(基于mtop)
WXJSExceptionProtocol 基于 MotuReport ,上报jsexception

6 接入热修复

6.1 指定Pod源

  1. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs-thirdpart.git'

6.2 添加依赖

  1. pod 'AlicloudLua', '5.1.4.2'
  2. pod 'AlicloudUtils', '1.2.1'
  3. pod 'ZipArchive', '~> 1.4.0'
  4. pod 'AlicloudHotFixDebugEmas', '~> 1.0.3' // 调试用,可选
  5. 【特别注意】热修复SDK除了pod指定版本集成外,还需要手动集成两个framework进去。
  6. * 【注意】SDK文件为每个应用单独提供,用户每新建一个应用需首先获取应用的AppKey,然后请联系工作人员提供SDK文件。
  7. * SDK包括:
  8. * AlicloudHotFixEMAS.framework
  9. * arp.framework
  10. > 当前SDK版本:v1.0.5。(在AlicloudHotFixEmas.framework/Headers/AlicloudHotFix.h中查看)
  11. * 直接把下载SDK目录中的Framework拖入对应Target下即可,在弹出框勾选`Copy items if needed`

(~>为模糊指定版本号方式,~> 1.0.0表明引用版本位于1.0.0 <= version < 1.1.0之间的最新版本SDK,用户可参考Podfile Syntax Reference,根据项目需要指定SDK版本。)

注意,若SDK集成过程中出现UTDID冲突,请参考:阿里云-移动云产品SDK UTDID冲突解决方案

6.3 热修复相关方法

  1. /**
  2. 获取热修复实例
  3. */
  4. + (instancetype)sharedInstance;
  5. /**
  6. 初始化SDK
  7. @param appId 应用AppId
  8. @param callback 回调
  9. */
  10. - (void)initWithAppId:(NSString *)appId
  11. callback:(HotFixCallbackHandler)callback;
  12. /**
  13. 手动设置补丁拉取时的App版本号,SDK初始化前调用
  14. (默认获取"CFBundleShortVersionString")
  15. @param appVersion App版本号
  16. */
  17. - (void)setAppVersion:(NSString *)appVersion;
  18. /**
  19. 打开日志开关
  20. @param enabled YES: 打开日志; NO:关闭日志
  21. */
  22. - (void)setLogEnabled:(BOOL)enabled;
  23. /**
  24. 从服务端加载补丁
  25. @param callback 回调
  26. */
  27. - (void)loadPatch:(HotFixCallbackHandler)callback;
  28. /**
  29. 清空本地补丁
  30. */
  31. - (void)cleanPatch;
  32. /**
  33. 设置服务地址
  34. */
  35. - (void)setServerURL:(NSString *)url;
  • appId信息,参考2.1章节正常设置即可。

6.4 热修复初始化示例

  1. #import <AlicloudHotFixDebugEmas/AlicloudHotFixDebugServiceEmas.h>
  2. #import <AlicloudHotFixEmas/AlicloudHotFixServiceEmas.h>
  3. hotfixService = [AlicloudHotFixServiceEmas sharedInstance];
  4. [hotfixService setLogEnabled:YES];
  5. [hotfixService setAppVersion:@"1"];
  6. [hotfixService initWithAppId:testAppId callback:^(BOOL res, id data, NSError *error) {
  7. if (res) {
  8. NSLog(@"HotFix SDK init success.");
  9. } else {
  10. NSLog(@"HotFix SDK init failed, error: %@", error);
  11. }
  12. }];
  13. // 从服务端加载补丁
  14. [hotfixService loadPatch:^(BOOL res, id data, NSError *error) {
  15. if (res) {
  16. NSLog(@"Load patch success.");
  17. } else {
  18. NSLog(@"Load patch failed, error: %@", error);
  19. }
  20. }];

7 高级特性-自定义服务地址

平时开发过程中,客户端和服务端为了方便联调新的协议,通常需要在测试环境(指定IP地址和端口)中来验证。ACCS中的网络模块也支持这种方法。

7.1 新建自定义策略类

  1. //新建MyPolicyCenter类,重写下面指定的方法
  2. @interface MyPolicyCenter : NSObject <NWPolicyDelegate>
  3. @end
  4. @implementation MyPolicyCenter
  5. - (nullable NWPolicy *)queryPolicy:(nonnull NSString *)host
  6. withScheme:(nonnull NSString *)scheme
  7. withAcceleration:(BOOL)acceleration
  8. withSuccessAisle:(BOOL)success {
  9. if ([host isEqualToString:某某域名 && acceleration==YES) {
  10. NSString *ip = [ipPort objectAtIndex:0];
  11. NSString *port = [ipPort objectAtIndex:1];
  12. NWAisle *aisle = [NWAisle new];
  13. aisle.protocol = @"http2";
  14. aisle.ip = ip; //指定某某域名连接到新的IP地址
  15. aisle.port = [port intValue]; //指定某某域名连接到新的端口
  16. aisle.encrypt = YES;
  17. aisle.auth = YES;
  18. aisle.publickey = @"emas";
  19. NWPolicy *policy = [NWPolicy new];
  20. policy.type = kNWAislePolicy;
  21. policy.host = host;
  22. policy.aisles = @[ aisle ];
  23. return policy;
  24. }
  25. return nil;
  26. }
  27. - (nullable NSString *)queryScheme:(nonnull NSString *)host {
  28. // 如果需要对该域名的所有请求的url的scheme进行修改,可以在这里进行
  29. // 所有 www.abc.com 的域名使用 https
  30. if ([host isEqualToString:某某域名) {
  31. return @"https";
  32. }
  33. // 所有 www.xyz.com 的域名使用 http
  34. if ([host isEqualToString:xx域名) {
  35. return @"http";
  36. }
  37. // 没有需求的直接返回nil
  38. return nil;
  39. }
  40. - (nonnull NSString *)queryCname:(nonnull NSString *)host {
  41. return host;
  42. }
  43. - (void)updateAisleStatus:(nonnull NWAisle *)aisle
  44. withHost:(NSString*)host
  45. withStatus:(NWAisleStatus)status {
  46. // do something
  47. }
  48. - (nullable NWPolicy *)queryPolicy:(nonnull NSString *)host {
  49. return nil;
  50. }
  51. @end

7.2 指定自定义策略

  1. policyCenter = [[MyPolicyCenter alloc] init];
  2. [NWNetworkConfiguration shareInstance].policyDelegate = policyCenter

8 初始化通用库

8.1 指定Pod源

  1. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs.git'

8.2 添加依赖

  1. pod 'UserTrack', '6.3.5.100005-poc'
  2. pod 'Reachability', '3.2'
  3. pod 'FMDB', '2.7.2'
  4. pod 'NetworkSDK', '10.0.4.2'
  5. pod 'tnet', '10.2.0'

8.3 通用库初始化示例

  1. #import <UT/UTAnalytics.h>
  2. #import <UT/AppMonitor.h>
  3. #import <NetworkSDK/NetworkCore/NWNetworkConfiguration.h>
  4. #import <NetworkSDK/NetworkCore/NetworkDemote.h>
  5. #import <NetworkSDK/NetworkCore/NWuserLoger.h>
  6. // UT初始化部分
  7. [[UTAnalytics getInstance] turnOffCrashHandler];
  8. [[UTAnalytics getInstance] turnOnDebug]; // 打开调试日志
  9. //scheme指定了埋点上报组件的请求协议,可以是https或者http
  10. [[UTAnalytics getInstance] setTimestampHost:timestampHost scheme:scheme];
  11. [[UTAnalytics getInstance] setAppKey:AppKey secret:AppSecret];
  12. [[UTAnalytics getInstance] setChannel:channel];
  13. [[UTAnalytics getInstance] setAppVersion:appversion];
  14. [AppMonitor disableSample]; // 调试使用,上报不采样,建议正式发布版本不要这么做
  15. // 网络库初始化部分
  16. [NWNetworkConfiguration setEnvironment:release];
  17. NWNetworkConfiguration *configuration = [NWNetworkConfiguration shareInstance];
  18. [configuration setIsUseSecurityGuard:NO];
  19. [configuration setAppkey:AppKey];
  20. [configuration setAppSecret:AppSecret];
  21. [configuration setIsEnableAMDC:NO];
  22. [NetworkDemote shareInstance].canInitWithRequest = NO;
  23. setNWLogLevel(NET_LOG_DEBUG); // 打开调试日志

9 初始化ACCS

9.1 指定Pod源

  1. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs.git'

9.2 添加依赖

  1. pod 'UserTrack', '6.3.5.100005-poc'
  2. pod 'Reachability', '3.2'
  3. pod 'FMDB', '2.7.2'
  4. pod 'NetworkSDK', 10.0.4.2'
  5. pod 'tnet', '10.2.0'
  6. pod 'TBAccsSDK', '10.0.7'

9.3 ACCS初始化示例

  • 由于ACCS依赖通用库,所以初始化ACCS前,要先初始化通用库.
  • 网关初始化顺序:通用库-> ACCS

1) 通用库初始化参考

2) ACCS初始化

  1. #import <TBAccsSDK/TBAccsManager.h>
  2. // Accs依赖通用库,记得初始化Accs前,要先初始化通用库
  3. //...
  4. //init common config
  5. //...
  6. // ACCS初始化部分
  7. void tbAccsSDKSwitchLog(BOOL logCtr);
  8. tbAccsSDKSwitchLog(YES); // 打开调试日志
  9. TBAccsManager *accsManager = [TBAccsManager accsManagerByHost:ACCSDomain];
  10. [accsManager setSupportLocalDNS:YES];
  11. accsManager.slightSslPublicKeySeq = ACCS_PUBKEY_PSEQ_EMAS;
  12. [accsManager startAccs];
  13. [accsManager bindAppWithAppleToken: nil
  14. callBack:^(NSError *error, NSDictionary *resultsDict) {
  15. if (error) {
  16. NSLog(@"\n\n绑定App出错了 %@\n\n", error);
  17. }
  18. else {
  19. NSLog(@"\n\n绑定App成功了\n\n");
  20. }
  21. }];

10 初始化网关

10.1 指定Pod源

  1. source 'git@gitlab-ce.emas-poc.com:EMAS-iOS/emas-specs.git'

10.2 添加依赖

  1. pod 'UserTrack', '6.3.5.100005-poc'
  2. pod 'Reachability', '3.2'
  3. pod 'FMDB', '2.7.2'
  4. pod 'NetworkSDK', '10.0.4.2'
  5. pod 'tnet', '10.2.0'
  6. pod 'MtopSDK', '10.0.6'
  7. pod 'mtopext/MtopCore', '10.0.6'

10.3 网关初始化示例

  • 由于网关依赖通用库,所以初始化网关前,要先初始化通用库.
  • 网关初始化顺序:通用库-> 网关

1) 通用库初始化参考

2) 网关初始化

  1. #import <MtopSDK/MtopSDK.h>
  2. #import <MtopCore/MtopService.h>
  3. // MTOP初始化部分
  4. TBSDKConfiguration *config = [TBSDKConfiguration shareInstanceDisableDeviceID:YES andSwitchOffServerTime:YES];
  5. config.environment = TBSDKEnvironmentRelease;
  6. config.safeSecret = NO;
  7. config.appKey = AppKey;
  8. config.appSecret = AppSecret;
  9. config.wapAPIURL = MTOPDomain;//设置全局自定义域名
  10. config.wapTTID = CHANNELID; //渠道ID
  11. openSDKSwitchLog(YES); // 打开调试日志
  12. //config.enableHttps = NO; //若有降级到HTTP抓包需求,请设置为NO,否则不要设置。

11 Q&A

11.1 平台打包或者本地pod update的时候出错

  • The version of CocoaPods used to generate the lockfile (1.3.1) is higher than the version of the current executable (1.2.0). Incompatibility issues may arise.
  1. 答:出现这种情况是提交的工程文件中含义Podfile.lock文件,需要把该文件删除后重新提交到git上,再重新操作即可。

11.2 Clone出错

  • Cloning spec repo emas-ha-emas-specs from git@gitlab.emas-ha.cn:root/emas-specs.git[!] Unable to add a source with url git@gitlab.emas-ha.cn:root/emas-specs.git named emas-ha-emas-specs.You can try adding it manually in ~/.cocoapods/repos or via pod repo add.
  1. 答:出现这种情况是没有改工程的访问权限,此时记得本地的ssh key里面的公钥配置到git仓库上