关于 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
的私有方法,有可能会被拒,酌情考虑使用。
如果害怕被拒上架的可以看看这个,然后考虑是否使用私有方法
网友评论