iOS 常见问题

如何解决 H5 容器定位偏移问题?

解答:在使用 mPaaS 容器的过程中可能会遇到 H5 容器定位偏移的问题,请参考以下方法进行设置更新:

- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    //跳过 LBS 定位
    [LBSmPaaSAdaptor sharedInstance].shouldSkipLBSLocation = YES;

    .......
    
}

预置离线包使用 H5_json.json 文件不生效怎么办?

解答:在 10.1.32 基线中, 只支持 plist 格式。在 10.1.60 基线中, plist 和 JSON 格式都支持。

如何获取已安装的离线包应用信息?

解答:参考代码 NSDictionary *installedApps = [NAMServiceGet() installApps:nil];

如何强制更新全部离线包信息?

解答:可以使用封装的 requestAllNebulaApps 方法进行全量更新。

[[MPNebulaAdapterInterface shareInstance]requestAllNebulaApps:^(NSDictionary *data, NSError *error) {

 }];

在 iOS 13 中,vux-ui pulldown 组件在H5容器中存在滑动卡死的情况

解答:这是因为触发了 UIWebview 在 iOS 系统中的 bug,可以考虑切换成 WKWebview 或更换前端组件。切换为 WKWebview 的方法请参考文档 mPaaS 10.1.60 适配 WKWebView

如何查看当前应用已注册的所有 JSAPI 和 Plugins?

解答:打开一个 H5 页面,进入 Xcode View 层级页面,在 lldb 控制台使用 po [[PSDService sharedInstance] jsApis] 查看所有 JSAPI。同理使用 po [[PSDService sharedInstance] plugins] 查看所有注册的 Plugins。

1

如何在 JSAPI 或 Plugin 中获取当前 H5 页面的 UIViewController 和 Webview 对象?

解答:在实际执行过程中,Plugin 可直接拿到参数 event.context,JSAPI 中可获取到 context,在上下文 PSDContext 对象中,可以取到您想要的所有信息或引用,比如当前控制器 event.currentViewController 的引用,当前 WebView 的引用context.currentViewController.psdContentView 等等。

2

3

如何获取当前页面加载时前端传入的启动参数?

解答:直接获取当前 VC 的 psdScene.createParam.expandParams 属性。

修改1.jpg

如何限制 JSAPI 只在某个特定离线包中起作用?

解答:在 JSAPI 的实际执行方法中,获取当前页面所属离线包的 appId,决定是否执行逻辑就可以了。

5

如何拦截页面 URL?

解答:您可以自定义 Plugin,通过监听事件来实现。

  • 监听事件名称:

    [PSDProxy addEventListener:kEvent_Proxy_Request_Start_Handler withListener:self useCapture:YES];
    `
  • 拦截处理:

    else if ([kEvent_Proxy_Request_Start_Handler isEqualToString:event.eventType]
          && [event isKindOfClass:[PSDProxyEvent class]] ){
          NSLog(@"-----kNBEvent_Scene_NavigationItem_Right_Setting_Click----");
          PSDProxyEvent *proxyEvent = (PSDProxyEvent*) event;
          NSMutableURLRequest *redirectReq = proxyEvent.request.mutableCopy;
          NSString *appId = event.context.currentSession.createParam.expandParams[@"appId"];
          NAMApp *app = [NAMServiceGet() findApp:appId version:nil];
          NSString *fallBackUrl = app.fallback_host;
          NSString *vhost = app.vhost;;
          NSString *url = redirectReq.URL.absoluteString;
          NSLog(@"url__%@______fallBackUrl:%@",url,fallBackUrl);
         if ([url containsString:@"www.baidu.com"]) {
             [proxyEvent preventDefault];
    }}

如何在 Native 手动调用 JSAPI ?

解答:您可以直接调用当前页面所属基类的 callHandler 方法,代码示例如下所示。

修改2.jpg

控制台发布新版本离线包后,客户端不能正常加载到新的离线包

解答:在查看此问题解决方案前,确认您已理解 离线包更新原理,客户端不能正常加载新包,离线包渲染在任一阶段都有可能出错,下面将一一进行排查。

  • 查看全量更新离线包的 RPC 返回结果,在控制台搜索 bizType: 4 确认返回的离线包详情,确认已经拉取了控制台发布的最新包信息。

  • 上一步检查通过后,查看沙盒目录下离线包是否解压成功(若当前离线包有引用全局资源包中内容,此解压目录下同样需要有全局资源包)。 8

  • 若上一步中沙盒目录下无对应离线包,可先暂时关闭离线包验签,删除 App 重新运行。若关闭验签后加载正常,说明离线包加签私钥和客户端验签公钥不一致,请更新客户端对应的公钥信息。

  • 若上述步骤检查都通过,离线包更新仍失败,可用 Safari 调试对应 H5 页面,具体查看报错原因。如全局资源包路径不正确,离线包加载的 URL 不存在等。 9

为什么打开某个离线包 H5 页面会白屏或出现 400 错误?

解答:页面白屏或出现 400 错误,一般为本地离线包加载失败导致走了在线 fallback 地址,而对应页面的 fallback 地址不存在,导致页面加载失败。

  • 按上述离线包问题排查客户端离线包加载失败的原因。

  • 针对加载在线 fallback 地址失败的问题,确认对应离线包版本生成正确,且已在控制台已上传,包括普通离线包和全局资源包,具体请参考 生成离线包

  • 预置离线包若出现在线 fallback 地址失败的问题,先保证预置的离线包在控制台同样也上传。

  • 保证本地预置包信息中 fallback_base_url 与从控制台下载的 h5_json.json 配置文件中 fallback_base_url 一致。 1112

  • 并且 fallback_base_url + main_url拼接的地址在浏览器可正常加载。

    修改3.jpg

怎样禁止 H5 页面的手势侧滑返回功能?

解答:支持由前端 H5 页面禁止和原生 H5 容器基类禁止。

  • 前端 H5 页面禁止:调用 setGestureBack JSAPI 实现。适用于某一个页面需要禁止手势侧滑返回的场景

    AlipayJSBridge.call('setGestureBack',{val:false});
  • 原生 H5 容器基类禁止:在基类的 viewDidAppear 方法中调用系统禁止侧滑返回的接口,同时设置 guestBack参数。适用于多个或所有 H5 页面需要禁止手势侧滑返回的场景。

      - (void)viewDidAppear:(BOOL)animated {
          [super viewDidAppear:animated];
    
          self.options.gestureBack = NO;
          if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
              self.navigationController.interactivePopGestureRecognizer.enabled = NO;
          }
      }

如何判断当前页面是小程序中的页面?

解答:获取当前页面所在的 session,调用 isTinyAppWithSession 接口判断。代码示例如下:

PSDSession *session = self.psdSession;
BOOL isTinyApp = [NBUtils isTinyAppWithSession:session];

H5页面如何传递自定义参数?

解答:根据传参方式,分为一下几种场景:

  • 原生 - H5:调用 startH5ViewControllerWithParams 方法时传递 [[MPNebulaAdapterInterface shareInstance] startH5ViewControllerWithParams:@{@"url": @"https://tech.antfin.com", @"key1":@"value1"}];

  • 原生 - 离线包:调用 startH5ViewControllerWithNebulaApp 方法时传递 [[MPNebulaAdapterInterface shareInstance] startH5ViewControllerWithNebulaApp:@{@"appId":@"70000000",@"param":@{@"key2":@"value2"}}];

  • H5 - H5: 调用 pushWindow 时将自定义参数写在 passData 中:

    AlipayJSBridge.call('pushWindow', {
    // 要打开页面的 URL
    url: 'https://m.taobao.com/',
    // 打开页面的配置参数
    param: {
      readTitle: true,    //自动读取 title
      showOptionMenu: false,    // 隐藏右边菜单
    transparentTitle:'always',
    },
    // 用于给新开的页面传递参数,可选
    // 在新开的页面使用 AlipayJSBridge.startupParams 可以获取到 passData
    passData: {
      key1: "key1Value",
      key2: "key2Value"
    }
    });
  • H5 - 离线包:调用 startApp JSAPI 时将自定义参数写在 param 中:

    AlipayJSBridge.call('startApp', {
    appId: '70000000',
    param: {
    key1:'value1'
    }
    }, function(result) {
    // noop
    });

如何获取 H5 页面传递的参数?

解答:分为前端获取和原生获取两种场景:

  • 前端获取:通过 startupParams 方法获取。

    // 当前页面的启动参数
    AlipayJSBridge.startupParams
  • 原生获取:通过当前页面所在的 VC 对象获取。

    // 当前页面的启动参数
    NSDictionary *expandParams = self.psdScene.createParam.expandParams;
    NSLog(@"[mpaas] expandParams: %@", expandParams);

如何拦截 JSAPI 调用?

解答:您可以自定义 Plugin,通过监听事件来实现。

  • 监听事件名称:kEvent_Invocation_Event_Start

  • 拦截处理:获取到 JSAPI 的名称、传递的参数等。

    else if([kEvent_Invocation_Event_Start isEqualToString:event.eventType]) {
          PSDInvocationEvent * invocationEvent = (PSDInvocationEvent *)event;
          NSString * apiName = invocationEvent.invocationName;
          if([apiName isEqualToString:@"setOptionMenu"] || [apiName isEqualToString:@"showOptionMenu"] ) {
              NSLog(@"wwww");
          }
      }

首页嵌套 WebView,H5 容器无法释放如何处理?

背景:有一些特殊场景需要将离线包 H5 容器的 WebView 嵌套在 App 首页使用,当 WebView 的 super view 销毁时,H5 容器可能无法被销毁,从而导致内存泄露的问题。

示例代码:

image.png

解答:可以尝试通过以下方式进行处理。

image.png