美文网首页
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