美文网首页
UIWebView 进入后台,因为 OpenGL ES 导致 C

UIWebView 进入后台,因为 OpenGL ES 导致 C

作者: CoderGuogt | 来源:发表于2019-10-25 18:10 被阅读0次

    关于 UIWebView 使用进入后台,因为 OpenGL ES 的原因导致crash,报gpus_ReturnNotPermittedKillClient错误,不过这个在iOS11已经修复了。

    场景

    在使用 UIWebView 进入后台后,因为UIWebView在继续渲染,Apple 不允许这种操作,就给了一个 gpus_ReturnNotPermittedKillClient 异常。

    苹果官方文档解释

    对此有三种方案

    第一种方案
    • 使用 WKWebView替换 UIWebView
    第二种方案
    • 监听 App 进入到后台状态,对 UIWebView 进行加载空白页,间接达到停止渲染,但是用户体验不好
    第三种方案
    • 对webView的OpenGL ES 进行操作

      typedef void (*CallFuc)(id, SEL, BOOL);
      typedef BOOL (*GetFuc)(id, SEL);
      - (BOOL)webView:(UIWebView*)view enableGL:(BOOL)bEnable
      {
          BOOL bRet = NO;
          if (view == nil) return NO;
          do
          {
              Ivar internalVar = class_getInstanceVariable([view class], "_internal");
              if (!internalVar)
              {
                  NSLog(@"enable GL _internal invalid!");
                  break;
              }
          
              UIWebViewInternal* internalObj = object_getIvar(view, internalVar);
              Ivar browserVar = class_getInstanceVariable(object_getClass(internalObj), "browserView");
              if (!browserVar)
              {
                  NSLog(@"enable GL browserView invalid!");
                  break;
              }
          
              id webbrowser = object_getIvar(internalObj, browserVar);
              Ivar webViewVar = class_getInstanceVariable(object_getClass(webbrowser), "_webView");
              if (!webViewVar)
              {
                  NSLog(@"enable GL _webView invalid!");
                  break;
              }
          
              id webView = object_getIvar(webbrowser, webViewVar);
              if (!webView)
              {
                  NSLog(@"enable GL webView obj nil!");
              }
          
              if(object_getClass(webView) != NSClassFromString(@"WebView"))
              {
                  NSLog(@"enable GL webView not WebView!");
                  break;
              }
          
              SEL selector = NSSelectorFromString(@"_setWebGLEnabled:");
              IMP impSet = [webView methodForSelector:selector];
              CallFuc func = (CallFuc)impSet;
              func(webView, selector, bEnable);
          
              SEL selectorGet = NSSelectorFromString(@"_webGLEnabled");
              IMP impGet = [webView methodForSelector:selectorGet];
              GetFuc funcGet = (GetFuc)impGet;
              BOOL val = funcGet(webView, selector);
          
              bRet = (val == bEnable);
          
          } while(NO);
      
          return bRet;
      }
      

      监听方法

      // 进入前台
      - (void)applicationBecomeActive {
      
          [self webView:self.webView enableGL:YES];
      }
      
      // 进入到后台
      - (void)applicationEnterBackground {
      
          [self webView:self.webView enableGL:NO];
      }
      

      viewDidLoad 方法中监听进入后台、前台状态

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
      // app从后台进入前台都会调用这个方法
      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationWillEnterForegroundNotification object:nil];
      // 添加检测app进入后台的观察者
      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterBackground) name: UIApplicationDidEnterBackgroundNotification object:nil];
      

      这种方法使用到了UIWebView的私有方法,有可能会被拒,酌情考虑使用。
      如果害怕被拒上架的可以看看这个,然后考虑是否使用私有方法

    相关文章

      网友评论

          本文标题:UIWebView 进入后台,因为 OpenGL ES 导致 C

          本文链接:https://www.haomeiwen.com/subject/fkkevctx.html