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的报错堆栈和页面追踪就成了我们可以定位问题的主要依据。
首先学会看报错信息,其次也要善于处理这些内部类以及内部方法。
系统的东西没有暴露出来没有关系,我们的有的是方法去拿到他们,使用他们,只要没有触碰苹果的底线,有时候我们解决问题就是需要这样的“不择手段”。
网友评论