美文网首页
UIWebview,应用退到后台,崩溃解决方案

UIWebview,应用退到后台,崩溃解决方案

作者: 宋奕Ekis | 来源:发表于2019-10-19 13:27 被阅读0次

H2这边的电商业务正在飞速上升中,但是我们所有的第三方电商提供商——有赞,却有众多坑。

其中,最为严重的是应用切换到后台后,导致的崩溃的问题。
此问题已经和他们相关人员沟通过,并且此问题也曾经在YeahMobi的SDK中发生过。

报错信息如下:

0 libGPUSupportMercury.dylib    _gpus_ReturnNotPermittedKillClient + 12
1 AGXGLDriver   gldUpdateDispatch + 7136
2 libGPUSupportMercury.dylib    gpusSubmitDataBuffers + 176
3 AGXGLDriver   gldUpdateDispatch + 12704
4 WebCore   WebCore::GraphicsContext3D::reshape(int, int) + 528
5 WebCore   WebCore::WebGLRenderingContextBase::initializeNewContext() + 716
6 WebCore   WebCore::WebGLRenderingContextBase::WebGLRenderingContextBase(WebCore::HTMLCanvasElement*, WTF::RefPtr<WebCore::GraphicsContext3D>&&, WebCore::GraphicsContext3D::Attributes) + 516
7 WebCore   WebCore::WebGLRenderingContext::WebGLRenderingContext(WebCore::HTMLCanvasElement*, WTF::PassRefPtr<WebCore::GraphicsContext3D>, WebCore::GraphicsContext3D::Attributes) + 40
8 WebCore   WebCore::WebGLRenderingContextBase::create(WebCore::HTMLCanvasElement*, WebCore::WebGLContextAttributes*, WTF::String const&) + 1284
9 WebCore   WebCore::HTMLCanvasElement::getContext(WTF::String const&, WebCore::CanvasContextAttributes*) + 520
10 WebCore  WebCore::JSHTMLCanvasElement::getContext(JSC::ExecState&) + 216

从报错分析可以看出来,由于有赞使用的是webview渲染承载页面,并且使用了openGL进行渲染。但是应用切换到后台的时候,有赞会继续进行openGL的渲染,这是被苹果明令禁止的,所以导致了在后台应用直接被杀死,并且还上报了崩溃错误的事情发生。

在没有更新有赞的SDK之前,可以使用WKWebView进行页面承载,此时并不需要关心此问题,苹果已经做了优化。但是在最新的SDK中,有赞取消了对WKWebView的支持,此时不得不对UIWebView进行处理避免此问题。

想了很多方法,最终还是决定,我们手动关闭webview的openGL渲染,关闭openGL并不影响页面的加载。但是需要用到部分私有属性。
代码如下:

//uiwebiew内部加载js时,在切换到后台的时候可能导致gpus_ReturnNotPermittedKillClient错误
//需要在loadrequest之前设置bEnable为NO,或者在切换到后台的时候将bEnable设置为NO,切换到前台后再设置为YES
//bEnable为NO的时候关闭openGL渲染

typedef void (*CallFuc)(id, SEL, BOOL);
typedef BOOL (*GetFuc)(id, SEL);

+ (BOOL)webView:(UIWebView *)view enableGL:(BOOL)bEnable
{
    BOOL bRet = NO;
    //将以下代码放在一个执行一次的while循环中是为了把其中众多变量作为局部变量,统一释放
    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;
}

总结,很多第三方的问题都莫名其妙。

在看不到对方代码的情况下,bugly的报错堆栈和页面追踪就成了我们可以定位问题的主要依据。

首先学会看报错信息,其次也要善于处理这些内部类以及内部方法。

系统的东西没有暴露出来没有关系,我们的有的是方法去拿到他们,使用他们,只要没有触碰苹果的底线,有时候我们解决问题就是需要这样的“不择手段”。

相关文章

网友评论

      本文标题:UIWebview,应用退到后台,崩溃解决方案

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