webview中遇到的一些问题

App内接入第三方活动,每次重启进入活动都需要重新登陆

为了赶上一波活动的热潮,蹭蹭流量,app内接入了第三方的热门活动,用户在参与活动前需要先登录,用本app的token去换一个第三方账号的登陆的token,并在app内保存cookie,以保存用户的登录状态。

    // 設定 cookie
 NSURL *cookieHost=[NSURL URLWithString:self.url];
 NSDictionary *token = [NSDictionary dictionaryWithObjectsAndKeys:@"access_token", NSHTTPCookieName,
                                    [User currentUser].accessToken, NSHTTPCookieValue,
                                    @"/", NSHTTPCookiePath,
                                    [cookieHost host], NSHTTPCookieDomain,
                                    nil];

但是发现活动入口因为在app内一直保存,但用户每次重新进入app后都需要重新登陆,才能开始参与活动。这样产品当然是不答应的。后来发现之所以用户需要重新登录,是因为用户之前登陆保存的cookie失效了,app杀死时将原来设置的cookie清空了。

查了一下,发现还可以设置cookie的失效时间,即NSHTTPCookieExpires,还顺带在API里看到了NSHTTPCookieDiscard key值。说是discard cookie的标志,表示不希望被discard。

所以加了两个字段设置

    NSDate *expiresDate = [NSDate dateWithTimeIntervalSinceNow:3600*24];//1天后才失效
    token[NSHTTPCookieExpires] = expiresDate;
    [token removeObjectForKey:NSHTTPCookieDiscard];

嗯,然后就没有一直需要重新登录了。

webview加载的url路径中带”#“号

原来遇到一个问题是,老板分享了一个来自微信某公众号的技术帖,路径尾部有两个”##“号,分享到公司的app的 IM中,点击用webview页面打开链接,会报错,但在微信内部看是没有问题的。后来发现,如果在打开url之前,对url编码,

[NSURL URLWithString:[self.url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]

此时路径中的”井井”号被编码为 ‘%23%23’,使用编码后的url是可以正常打开的。但是带来了新的问题,如果所有url都进行编码的话,一些使用SPA(前端框架)框架下部署的页面,路径后面会带 井号,此时不可以对url编码,否则路径不识别。后来咨询H5的同事,一般的页面很少框架下会在路径中出现两个连续井号,然后测试发现如果我讲url中出现的连续井号,替换成一个井号,微信内的那个链接就能正常打开了,并且测试了以前出现的大量站外url,未发现异常。这一个看起来很不靠谱的解决方案。。。。

 //webview  URL碰到两个#号,就不认识了,将 n 个#号替换成一个#号
    NSString *regExpStr = @"#+";
    NSString *replacement = @"#";
    NSRegularExpression *regExp = [[NSRegularExpression alloc]initWithPattern:regExpStr options:NSRegularExpressionCaseInsensitive error:nil];
    url = [regExp stringByReplacingMatchesInString:url options:NSMatchingProgress range:NSMakeRange(0, url.length) withTemplate:replacement];

webview error code

webview在加载过程中会报一些奇奇怪怪得错,而出错后按照业务需求需要展示错误页面。就会有测试进场过来问,我这个页面明明可以打开,可是咱们app为什么打不开,展示错误页呀。。。。嗯,我的锅!
调试发现webview报错了,报错种类有这么些

  1. 当同时收到两个一样的请求时,webview会自动cancle其中一个,并抛出一个 -999的errorCode
  2. 当页面内元素或插件视图加载插件时,会抛出一个204的errorCode
  3. 当url链接有不符合url规范的字符时,会抛出一个101的errorCode
  4. 当缺乏https证书,却加载https协议链接时会抛出 -1202 的errorCode
    所以以上1,2,都可忽略,只需要失败回调里忽略就好
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
       if ([self isSpecialCancle:error.code]) {
        return;
    }
    [self addErrorPage];
}

- (BOOL)isSpecialCancle:(NSInteger)code {
    switch (code) {
        case -999:
            return YES;
            break;
        case -1003:
            return YES;
            break;
        case 204:
            return YES;//加载插件
            break;
        default:
            return NO;
            break;
    }
}

问题3可对url编码解决。问题4,解决方案就一搜一片了,只需要自定义NSURLConnection代理,在代理中信任此次请求便可,但最好的是制作https证书,或买专业机构的https证书。

[NSURLConnection connectionWithRequest:self.request delegate:self];
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    }
    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

webview 内js调用alert()函数,会crash

在调试过程中发现,js如果多次调用alert()函数,在8的系统上会引起crash,打印线程快照发现 alert() 函数实现调用的是系统私有api,用的是UIAlertView的私有函数,调用线程是js的线程。初步判断是在js线程调用UI操作,引起的crash。

因此解决方法是用原生方法覆盖js的alert函数

    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    //覆盖js的alert
    context[@"alert"] = ^(id msg){
        if ([msg isKindOfClass:[NSString class]]) {
            [UIAlertView alertViewWithTitle:(NSString*)msg message:nil cancelButtonTitle:@"确定" otherButtonTitles:nil onDismiss:^(NSInteger buttonIndex) {
            } onCancel:^{
            }];
            
        }
    };

Webview注入OC对象引起内存泄漏

在做hybrid功能时,因为要向H5暴露OC对象,并暴露协议方法,因此要向JsContext中注入OC对象代码如下:

JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[JSSDK_NATIVENAME] = self;

但最初hybrid没有形成规模和框架时,我们webController -> webview是强持有关系,webview -> JSContext 是系统定的强持有关系, 而此时context[JSSDK_NATIVENAME] = self 操作会让 JSContext强持有webController ,形成循环引用,导致内存泄漏。

所以中间需要引入一个webviewHandle

webController -> webview 强持有
webview -> JSContext 强持有
JSContext -> webviewHandle 强持有
webviewHandle ——> webController(或其他Module) 弱代理关系,来解除循环引用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容

  • WebView简介 String getUrl():获取当前页面的URL。 reload():重新reload当前...
    QM阅读 3,117评论 0 52
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    南城的人阅读 4,750评论 0 19
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    小庄bb阅读 3,509评论 3 25
  • Tips 由于WebView的用法实在太多,如果您只是想查询某个功能的使用——建议Ctrl+F(Commad+F)...
    BugDev阅读 7,748评论 11 109
  • 虞舜踏破江南路,娥英走尽湘水渡。 泪尽滴血神灵泣,昼开夜合相思树。 曼妙妖娆浓情意,倚竹眺望分明语。 淡雅艳丽几度...
    曦微w行走在路上阅读 660评论 6 6