如果您对禁用iOSWKWebView中的日期操作感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于禁用iOSWKWebView中的日期操作的详细内容,并且为您提供关于BAWKW
如果您对禁用 iOS WKWebView 中的日期操作感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于禁用 iOS WKWebView 中的日期操作的详细内容,并且为您提供关于BAWKWebView BAWKWebView 分类封装 WKWebView、iOS - WKWebView那些坑、ios uiwebview wkwebview注意点小记、iOS UIWebView 和 WKWebView 的 cookie 获取,设置,删除的有价值信息。
本文目录一览:- 禁用 iOS WKWebView 中的日期操作
- BAWKWebView BAWKWebView 分类封装 WKWebView
- iOS - WKWebView那些坑
- ios uiwebview wkwebview注意点小记
- iOS UIWebView 和 WKWebView 的 cookie 获取,设置,删除
禁用 iOS WKWebView 中的日期操作
如何解决禁用 iOS WKWebView 中的日期操作?
我在 iOS 应用程序中使用 WKWebView 显示的页面上有一个时间段选择器 Web 组件。
iOS 识别出给定的文本是一个日期,并在您点击该日期时提供操作。
有什么办法可以禁用它吗?是通过更改 HTML 代码还是配置 iOS WKWebView 实例?
HTML 代码:
<headerhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-dates-selector svelte-kvfxh4">
<divhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-day svelte-10whff3 today">
<spanhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-date-name svelte-10whff3">Thu</span>
<spanhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-date-nb svelte-10whff3">29 Jul</span>
</div>
<divhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-day svelte-10whff3">
<spanhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-date-name svelte-10whff3">Fri</span>
<spanhttps://www.jb51.cc/tag/csl/" target="_blank">cslot-date-nb svelte-10whff3">30 Jul</span>
</div>
//...
</header>
如果您按下一步,HTML 将更新并且该操作将不再出现。
解决方法
您可以使用以下 JavaScript 代码“覆盖”HTML 并禁用长按和链接触摸:
func webView(_ webView: WKWebView,didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.documentElement.style.webkitUserSelect=''none''")
webView.evaluateJavaScript("document.documentElement.style.webkitTouchCallout=''none''")
webView.evaluateJavaScript("var elems = document.getElementsByTagName(''a''); for (var i = 0; i < elems.length; i++) { elems[i][''href''] = ''javascript:(void)''; }")
}
BAWKWebView BAWKWebView 分类封装 WKWebView
BAWKWebView BAWKWebView 介绍
BAWKWebView
-
1、用分类封装 WKWebView,代码无任何侵入更改
-
2、用 block 方式实现所需代理回调,更加方便,代码更简洁
-
3、一行代码搞定 request、URL、URLString、本地 HTML文件、HTMLString等请求
-
4、一个 block 搞定 title、progress、currentURL、当前网页的高度等等所需
-
5、有博爱封装好的 BAWebViewController 可以直接使用,也可以参考自定义浏览器【参考demo】
-
6、WKWebView 自定义 request post 数据到 JS(使用分类)
-
7、WKWebView OC 拦截 JS URL 处理,详见demo
-
8、修复 WKWebView 中的 alert 不能弹出的 bug!(详见 demo5)
-
9、新增 cell 中 WKWebView 高度自适应 demo(demo 有小部分遗留问题待解决)
-
10、自定义修改 navigator.userAgent(详见 demo BAWebViewController)
BAWKWebView BAWKWebView 官网
https://github.com/BAHome/BAWKWebView
iOS - WKWebView那些坑
WKWebView 是苹果在 WWDC 2014 上推出的新一代 webView 组件,用以替代 UIKit 中笨重难用、内存泄漏的 UIWebView。WKWebView 拥有60fps滚动刷新率、和 safari 相同的 JavaScript 引擎等优势。
简单的适配方法本文不再赘述,主要来说说适配 WKWebView 过程中填过的坑以及善待解决的技术难题。
1、WKWebView 白屏问题
2、WKWebView Cookie 问题
3、WKWebView NSURLProtocol问题
4、WKWebView loadRequest 问题
5、WKWebView 页面样式问题
6、WKWebView 截屏问题
7、WKWebView crash问题
8、其它问题
参考链接:腾讯Bugly
ios uiwebview wkwebview注意点小记
概述
wkwebview是苹果公司推出的替代uiwebview的方案,它在内存占用和稳定性方面有很大的优势,性能对比此篇文章就不讲了。
但是就目前情况而言,uiwebview还有有一些不能被完全替代的原因,比如wkwebview无法用NSURLProtocol拦截请求,因此无法通过NSURLProtocol实现加载离线化资源。
本文主要是记录自己在使用的时候碰到的一些坑。
方法注入
uiwebview目前的方式就是直接通过JS定义方法,然后使用JSC来获得JS方法的回调。
wkwebview可以直接使用addScriptMessageHandler来添加需要监听的方法,然后在userContentController中处理监听事件。
主要的区别是,uiwebview的注入只对当前界面生效,在加载新的url或者界面刷新后就会失效。而wkwebview的注入对整个wkwebview生效,界面刷新不会对其有影响。
所以在uiwebview上如果有注入全局方法的需求,通过直接运行JS代码注入不可行,一般可以使用拦截自定scheme和host的方式来做方法注入。
cookie
uiwebview的cookie与NSHTTPCookieStorage 同步,每次访问都会带上NSHTTPCookieStorage 中的内容,包括在页面中输入document.cookie也能获取到NSHTTPCookieStorage 中的cookie。
wkwebview不是及时同步
但是wkwebview的cookie和NSHTTPCookieStorage 就不能及时同步,注意是不能及时同步,并不是不同步。主要体现在以下两个方面:
1、当NSHTTPCookieStorage 的中的cookie被修改了,cookie是会同步到wkwebview的,但是不是及时同步的,比如说我修改了NSHTTPCookieStorage的值之后然后马上打开一个wkwebview,wkwebview不一定能获取到我刚刚修改的cookie。
2、当我使用document.cookie在wkwebview中设置cookie的时候,我当前设置的cookie是会回写到NSHTTPCookieStorage中,但是也不是及时的。
由于不及时同步,我们就说一下可能会有的问题,举例两个场景:
1、wkwebview没有获取到cookie,然后触发登陆逻辑后修改NSHTTPCookieStorage 跳回wkwebview,这时候wkwebview很有可能还是没有cookie的,因为wkwebview的cookie不是及时同步的。
2、某一模块为了满足自己的需求,修改了NSHTTPCookieStorage 中的一个cookie,而这个cookie刚好和其他模块重名了,由于wkwebview会回写cookie到NSHTTPCookieStorage 中,因此它会把原来这个名字的cookie给覆盖掉。而不仅仅存在cookie的value被修改,导致其他模块cookie错误的的问题,如果expire被修改了,也同时会给其他模块带去cookie过期的问题。
wkwebview对cookie的处理
目前网上的处理方法主要有以下两种:
1、在webview发起请求的时候附带cookie。
2、在webview创建的时候js注入cookie。
这两个方法都能解决wkwebview不能及时同步NSHTTPCookieStorage 的问题,但是无法解决wkwebview的cookie修改后不能及时回写到NSHTTPCookieStorage 的问题。
还是举个例子:
第一个wkwebview中的JS修改了一段cookie之后,没过多久又打开了第二个wkwebview,第二个wkwebview是很可能获取不到第一个wkwebview对cookie的修改的。最根本原因就是由于wkwebview的cookie无法及时回写到NSHTTPCookieStorage 。
那么这种情况如何解决呢?答案就是wkProcessPool。
WKProcessPool
使用同一个WKProcessPool的wkwebview可以共享cookie数据,但是WKProcessPool中的cookie并不和NSHTTPCookieStorage 一样会本地存储。在APP重启后WKProcessPool中的cookie会被重置。
cookie仍然存在的问题
1、 第一个wkwebview中的JS修改了一段cookie之后,没过多久又打开了一个uiwebview,uiwebview如何能及时同步到wkwebview对cookie的修改?
2、如果某个模块在wkwebview中修改了cookie的值,导致NSHTTPCookieStorage 中的cookie被篡改或者过期,如何定位到该模块的问题?
iOS UIWebView 和 WKWebView 的 cookie 获取,设置,删除
Cookie简介 说到Cookie,或许有些小伙伴会比较陌生,有些小伙伴会比较熟悉。如果项目中,所有页面都是纯原生来实现的话,一般Cookie这个东西或许我们永远也不会接触到。但是,这里还是要说一下Cookie,因为它真的很重要,由它产生的一些坑也很多。
Cookie 在 web中应用比较多,主要是记录一个状态,比如我在网页上登录了,我就可以拿到网页登录后 Cookie,下次再 Cookie 的生效期内我就可以不用输入账号密码,直接跳转登录状态,在App中,Cookie最常用的也就是维持登录状态了.因为笔者最近就在做这个,其中也遇到过很多坑,这里说先踩坑和用法
iOS Cookie 的管理
NSHTTPCookie和NSHTTPCookieStorage iOS中进行HTTP网络请求Cookie管理主要由两个类负责,一个类是NSHTTPCookieStorage类,一个是NSHTTPCookie类。
NSHTTPCookieStorage
NSHTTPCookieStorage类采用单例的设计模式,其中管理着所有HTTP请求的Cookie信息 官方解释:NSHTTPCookieStorage 是一个用来管理 cookie 存储的单例。一个 NSHTTPCookie 单例代表一个 cookie。通常来讲,cookie 可以在应用间共享,并且在进程之间保持同步。 对于单进程,Session cookies (这里的 cookie 对象的 isSessionOnly 方法返回 YES
)是局部的并且不能被共享。
常用方法
// 获取单例对象
+ (NSHTTPCookieStorage *)sharedHTTPCookieStorage;
// 所有Cookie数据数组 其中存放NSHTTPCookie对象
@property (nullable , readonly, copy) NSArray<NSHTTPCookie *> *cookies;
// 手动设置一条Cookie数据
- (void)setCookie:(NSHTTPCookie *)cookie;
// 删除某条Cookie信息
- (void)deleteCookie:(NSHTTPCookie *)cookie;
// 删除某个时间后的所有Cookie信息 iOS8后可用
- (void)removeCookiesSinceDate:(NSDate *)date NS_AVAILABLE(10_10, 8_0);
// 获取某个特定URL的所有Cookie数据
- (nullable NSArray<NSHTTPCookie *> *)cookiesForURL:(NSURL *)URL;
// 为某个特定的URL设置Cookie
- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forURL:(nullable NSURL *)URL mainDocumentURL:(nullable NSURL *)mainDocumentURL;
// Cookie数据的接收协议
枚举如下:
typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) {
NSHTTPCookieAcceptPolicyAlways, //接收所有Cookie信息
NSHTTPCookieAcceptPolicyNever, //不接收所有Cookie信息
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain //只接收主文档域的Cookie信息
};
@property NSHTTPCookieAcceptPolicy cookieAcceptPolicy;
系统下面的两个通知与Cookie管理有关:
据说,在Mac OS是cookie可以共享的(Session cookies 不能共享),在Mac OS app中更改cookie的接收策略会影响到其他正在运行的在使用cookie storage的app.这时NSHTTPCookieStorage会发出两个通知:
// Cookie数据的接收协议改变时发送的通知
FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerAcceptPolicyChangedNotification;
// 管理的Cookie数据发生变化时发送的通知
FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerCookiesChangedNotification;
NSHTTPCookie介绍
NSHTTPCookie是具体的HTTP请求Cookie数据对象.
// 下面两个方法用于对象的创建和初始化 都是通过字典进行键值设置
- (nullable instancetype)initWithProperties:(NSDictionary<NSString *, id> *)properties;
+ (nullable NSHTTPCookie *)cookieWithProperties:(NSDictionary<NSString *, id> *)properties;
// 返回Cookie数据中可用于添加HTTP头字段的字典
+ (NSDictionary<NSString *, NSString *> *)requestHeaderFieldsWithCookies:(NSArray<NSHTTPCookie *> *)cookies;
// 从指定的响应头和URL地址中解析出Cookie数据
+ (NSArray<NSHTTPCookie *> *)cookiesWithResponseHeaderFields:(NSDictionary<NSString *, NSString *> *)headerFields forURL:(NSURL *)URL;
// Cookie数据中的属性字典
@property (nullable, readonly, copy) NSDictionary<NSString *, id> *properties;
// 请求响应的版本
@property (readonly) NSUInteger version;
// 请求相应的名称
@property (readonly, copy) NSString *name;
// 请求相应的值
@property (readonly, copy) NSString *value;
// 过期时间
@property (nullable, readonly, copy) NSDate *expiresDate;
// 请求的域名
@property (readonly, copy) NSString *domain;
//请求的路径
@property (readonly, copy) NSString *path;
// 是否是安全传输
@property (readonly, getter=isSecure) BOOL secure;
// 是否只发送HTTP的服务
@property (readonly, getter=isHTTPOnly) BOOL HTTPOnly;
// 响应的文档
@property (nullable, readonly, copy) NSString *comment;
// 相应的文档URL
@property (nullable, readonly, copy) NSURL *commentURL;
// 服务端口列表
@property (nullable, readonly, copy) NSArray<NSNumber *> *portList;
HTTP cookie的属性键 属性 | 解读
NSHTTPCookieName | Cookie的名字
NSHTTPCookieValue | Cookie的值
NSHTTPCookieOriginURL | 和域名一样,NSHTTPCookieDomain或NSHTTPCookieOriginURL必须指定一个值
NSHTTPCookieVersion | 接收器的版本
NSHTTPCookieDomain | 域名
NSHTTPCookiePath | Cookie 存放路径
NSHTTPCookieSecure | Cookie是否只应通过安全通道发送,设置Cookie的secure属性为true。
只会在HTTPS和SSL等安全协议中传输此类Cookie。默认为false
NSHTTPCookieComment | 包含Cookie的评论,只有有效的版本1的cookies或更高版本。 这头字段是可选的
NSHTTPCookieCommentURL | 接收器的评论URL
NSHTTPCookieDiscard | Cookie是否应在会议结束时丢弃NSString,字符串值必须是“true”或“假”。
这个字段是可选的。 默认为“假”,除非这是Cookie是第1版或以上,
NSHTTPCookieMaximumAge未指定,在这种情况下,它被假定为“TRUE”
NSHTTPCookieMaximumAge | NSString对象,包含一个整数,在Cookie内保持最多几秒 。
仅适用于第1版和更高版本的有效。 默认为“0”。 此字段是可选的
NSHTTPCookiePort | 接收机的端口
- UIWebView的 Cookie 机制
UIWebView 在浏览网页后会将网页中的 cookie 自动存入 NSHTTPCookieStorage 标准容器中,[NSHTTPCookieStorage sharedHTTPCookieStorage]这个单例管理,在后续访问中会将 cookie 自动带到 request 请求当中。并且在同一个app内多个UIWebView之间共享。
- webView 中获取 cookie
//加载成功
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *requestUrl = webView.request.URL.absoluteString;
NSLog(@" requestUrl: %@",requestUrl);
//设置原始 cookie 根据key 存储本地
NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
//网页加载完成取出 cookies
NSArray *nCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSHTTPCookie *cookie;
for (id c in nCookies) {
if ([c isKindOfClass:[NSHTTPCookie class]]) {
cookie=(NSHTTPCookie *)c;
//我这里是cookie存入字典中 去重
if ([cookie value]) {
//如果 vaule 值不为 nil 存入字典中,
[self.mutableDic setValue:[cookie value] forKey:[cookie name]];
}
//设置原始 cookie
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName];
[cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue];
[cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain];
[cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath];
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
[cookieArray addObject:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
//cookie 存入本地
[[NSUserDefaults standardUserDefaults] setObject:cookieArray forKey:@"cookieArray"];
[[NSUserDefaults standardUserDefaults] synchronize];
//下面 cookie 去重是为了得到 key=Value;形式的字符串,这里由于我有需求这样做,实际中下面可以忽略
NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
// cookie重复,先放到字典进行去重,再进行拼接
for (NSString *key in self.mutableDic) {
NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [self.mutableDic valueForKey:key]];
[cookieValue appendString:appendString];
}
NSLog(@"######################## %@ ####################",cookieValue);
- 设置 cookie
NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"];
NSLog(@"cookie dictionary found is %@",cookieDictionary);
if (cookieDictionary)
{
for (NSInteger i = 0; i < cookieDictionary.count; i++)
{
NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]);
NSDictionary *cookieDic = [cookieDictionary objectAtIndex:i];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDic];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
//设置请求之前加载 cookie 确保 cookie 在请求头之前设置
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.URLString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//加载网页
[self.webView loadRequest:request];
- 删除 cookie
// 清空 cookie
- (void)deleteCookie {
// 清空 cookie
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]];
for (id obj in _tmpArray) {
[cookieJar deleteCookie:obj];
}
}
- WKWebView 的 Cookie 机制
NSURLCache和NSHTTPCookieStroage无法操作(WKWebView)WebCore进程的缓存和Cookie WKWebView实例将会忽略任何的默认网络存储器(NSURLCache, NSHTTPCookieStorage, NSCredentialStorage) 和一些标准的自定义网络请求类(NSURLProtocol,等等.),WKWebView实例不会把Cookie存入到App标准的的Cookie容器(NSHTTPCookieStorage)中,因为 NSURLSession/NSURLConnection等网络请求使用NSHTTPCookieStorage进行访问Cookie,所以不能访问WKWebView的Cookie,现象就是WKWebView存了Cookie,其他的网络类如NSURLSession/NSURLConnection却看不到。这是很多人的说法。 还有一种是说法是通过实践发现 WKWebView 实例其实也会将 Cookie 存储于 NSHTTPCookieStorage 中,但存储时机有延迟,因为WKWebView内也有cookie的容器,而且每隔一段时间就和app侧NSHTTPCookieStorage进行同步,而且这个同步是进程级别的同步,而且这个同步是单向。 至于以上两种说法,最终WKWebView Cookie 问题在于 WKWebView 发起的请求不会自动带上存储于 NSHTTPCookieStorage 容器中的 Cookie。
-
iOS11 iOS11 的 API 可以解决该问题,只要是存在 WKHTTPCookieStore 里的 cookie,WKWebView 每次请求都会携带,存在 NSHTTPCookieStorage 的cookie,并不会每次都携带。于是会发生首次 WKWebView 请求不携带 Cookie 的问题。
-
ios 11 WKWebView cookie 的注入
在执行 -[WKWebView loadReques:] 前将 NSHTTPCookieStorage 中的内容复制到 WKHTTPCookieStore 中,以此来达到 WKWebView Cookie 注入的目的。示例代码如下:
[self copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:^{
NSURL *url = [NSURL URLWithString:@"https://www.v2ex.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
}];
- (void)copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:(nullable void (^)())theCompletionHandler; {
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore;
if (cookies.count == 0) {
!theCompletionHandler ?: theCompletionHandler();
return;
}
for (NSHTTPCookie *cookie in cookies)
{
[cookieStroe setCookie:cookie completionHandler:^{
if ([[cookies lastObject] isEqual:cookie])
{
!theCompletionHandler ?: theCompletionHandler();
return;
}
}];
}
}
-
ios11 之前 注入 Cookie 就是从之前保存 cookie 的 NSHTTPCookieStorage 中取出相关 Cookie,然后在再次请求访问的时候在 request 中注入 Cookie。注入Cookie同样有多种方式。
-
1.JS注入1
//取出 storage 中的cookie并将其拼接成正确的形式
NSArray<NSHTTPCookie *> *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSMutableString *jscode_Cookie = [@"" mutableCopy];
[tmp enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
{
NSLog(@"%@ = %@", obj.name, obj.value);
[jscode_Cookie appendString:[NSString stringWithFormat:@"document.cookie = ''%@=%@'';", obj.name, obj.value]];
}];
WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: @"" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];
- JS注入2
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
[webView evaluateJavaScript:@"document.cookie =''TeskCookieKey1=TeskCookieValue1'';" completionHandler:^(id result, NSError *error) {
//...
}];
}
- NSMutableURLRequest 注入Cookie
NSURL *url = request.URL;
NSMutableString *cookies = [NSMutableString string];
NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
NSArray *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSDictionary *dicCookies = [NSHTTPCookie requestHeaderFieldsWithCookies:tmp];
NSString *cookie = [self readCurrentCookie];
[requestObj setValue:cookie forHTTPHeaderField:@"Cookie"];
[_webView loadRequest:requestObj];
-(NSString *)readCurrentCookie
{
NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary];
NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
[cookieDic setObject:cookie.value forKey:cookie.name];
}
// cookie重复,先放到字典进行去重,再进行拼接
for (NSString *key in cookieDic) {
NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]];
[cookieValue appendString:appendString];
}
return cookieValue;
}
获取Cookie
由于 WKWebView 的 Cookie 存储容器 WKWebsiteDataStore 是私有存储,所以无法从这里获取到Cookie,目前的方法是(1)从网站返回的 response headerfields 中获取。(2)通过调用js的方法获取 cookie。
- 1.从网站返回的 response headerfields 中获取,因为cookie都存在http respone的headerfields,找到能获得respone的WKWebView回调,打印
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
//读取wkwebview中的cookie 方法1
for (NSHTTPCookie *cookie in cookies) {
// [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
NSLog(@"wkwebview中的cookie:%@", cookie);
}
//读取wkwebview中的cookie 方法2 读取Set-Cookie字段
NSString *cookieString = [[response allHeaderFields] valueForKey:@"Set-Cookie"];
NSLog(@"wkwebview中的cookie:%@", cookieString);
//看看存入到了NSHTTPCookieStorage了没有
NSHTTPCookieStorage *cookieJar2 = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in cookieJar2.cookies) {
NSLog(@"NSHTTPCookieStorage中的cookie%@", cookie);
}
//下面是将 原始cookie本地 化
NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName];
[cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue];
[cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain];
[cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath];
[cookieProperties setObject:[NSNumber numberWithInt:cookie.version] forKey:NSHTTPCookieVersion];
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
[cookieArray addObject:cookieProperties];
}
[[NSUserDefaults standardUserDefaults] setValue:cookieArray forKey:@"cookieArray"];
[[NSUserDefaults standardUserDefaults] synchronize];
decisionHandler(WKNavigationResponsePolicyAllow);
}
// 页面加载完成之后调用需要重新给WKWebView设置Cookie防止因为a标签跳转,导致下一次跳转的时候Cookie丢失。
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
//取出cookie
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
//js函数
NSString *JSFuncString =
@"function setCookie(name,value,expires)\
{\
var oDate=new Date();\
oDate.setDate(oDate.getDate()+expires);\
document.cookie=name+''=''+value+'';expires=''+oDate+'';path=/''\
}\
function getCookie(name)\
{\
var arr = document.cookie.match(new RegExp(''(^| )''+name+''=({FNXX==XXFN}*)(;|$)''));\
if(arr != null) return unescape(arr[2]); return null;\
}\
function delCookie(name)\
{\
var exp = new Date();\
exp.setTime(exp.getTime() - 1);\
var cval=getCookie(name);\
if(cval!=null) document.cookie= name + ''=''+cval+'';expires=''+exp.toGMTString();\
}";
//拼凑js字符串
NSMutableString *JSCookieString = JSFuncString.mutableCopy;
for (NSHTTPCookie *cookie in cookieStorage.cookies) {
NSString *excuteJSString = [NSString stringWithFormat:@"setCookie(''%@'', ''%@'', 1);", cookie.name, cookie.value];
[JSCookieString appendString:excuteJSString];
}
//执行js
[webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error) {
NSLog(@"%@",error);
}];
}
- 通过 JS 获取 cookie
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
[webView evaluateJavaScript:[NSString stringWithFormat:@"document.cookie"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
if (response != 0) {
NSLog(@"\n\n\n\n\n\n document.cookie%@,%@",response,error);
}
}];
}
##注意 document.cookie 的方法获取 cookie并不支持跨越获取,如果设置 httponly则获取不到 cookie 不论是(1)还是(2)方法,似乎都无法解决302请求的 Cookie 问题。举例来说,假设你要访问网站A,在A中点击登录,跳转页面到B地址,在B中完成登录之后302跳转回A网站。此时cookie是存在于B地址的 response 中的,在A地址的 response 中并没有 cookie 的字段。然而我们只能获取到A地址的 response ,无法截获到B地址的response。因此获取不到该类型网站的 cookie 。 由于我并没有遇到302这样的问题,所有看了下网上的资料,希望对遇到这个问题的小伙伴一下办法,网上给出的解决办法是:
- 1.加载一个本地为空的html,域名指向你的第一次加载的url的域名。
//加载本地html
[self.webView loadHTMLString:@"" baseURL:[NSURL URLWithString:@"https:/a.com"]];
- 2.通过以下方法,在第一次加载完成后,将需要设置的Cookies设置到WKWebView中,因为是加载的本地的html以下方法会立即执行。
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
if (isFirstLoaded) {
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
//js函数
NSString *JSFuncString =
@"function setCookie(name,value,expires)\
{\
var oDate=new Date();\
oDate.setDate(oDate.getDate()+expires);\
document.cookie=name+''=''+value+'';expires=''+oDate+'';path=/''\
}";
//拼凑js字符串,按照自己的需求拼凑Cookie
NSMutableString *JSCookieString = JSFuncString.mutableCopy;
for (NSHTTPCookie *cookie in cookieStorage.cookies) {
if (![cookie.name isEqualToString:@"__cust"]) {
NSString *excuteJSString = [NSString stringWithFormat:@"setCookie(''%@'', ''%@'', 3);", cookie.name, cookie.value];
[JSCookieString appendString:excuteJSString];
}
}
//执行js
[webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error)
{
//加载真正的第一次Request
[self loadRealRequest];
}];
}
}
如果cookie 存储到本地获取本地的 cookie
//修改从 storage 中读取 cookie 的方法
-(NSString *)readCurrentCookie{
NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"];
NSLog(@"cookie dictionary found is %@",cookieDictionary);
for (int i=0; i < cookieDictionary.count; i++) {
NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]);
NSMutableDictionary* cookieDictionary1 = [[NSUserDefaults standardUserDefaults] valueForKey:[cookieDictionary objectAtIndex:i]];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDictionary1];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary];
NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
[cookieDic setObject:cookie.value forKey:cookie.name];
}
// cookie重复,先放到字典进行去重,再进行拼接
for (NSString *key in cookieDic)
{
NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]];
[cookieValue appendString:appendString];
}
return cookieValue;
}
清除 cookie
#pragma mark - 清空cookie
-(void)deleCookie {
// NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
// NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]];
// for (id obj in _tmpArray) {
// [cookieJar deleteCookie:obj];
// }
if (@available(iOS 9.0, *)) {//iOS9及以上
WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore];
[dateStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records)
{
for (WKWebsiteDataRecord *record in records)
{
//取消备注,可以针对某域名做专门的清除,否则是全部清除
//if ( [record.displayName containsString:@"baidu"])
//{
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes
forDataRecords:@[record] completionHandler:^
{
NSLog(@"Cookies for %@ deleted successfully",record.displayName);
}];
//}
}
}];
}
else { //iOS9以下
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"];
NSError *errors;
[[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors];
}
}
##最后 UIWebView 和 WKWebView 所遇到问题 cookie 同步,获取,删除,设置这些问题,目前就这么多解决办法吧,我一开始尝试用 WKWebView 获取 cookie 但是最后遇到网页跨域问题以及低版本兼容问题我还是换回 UIWebView 了,如果有更好的解决办法可以在下面留言,谢谢!
来自:https://www.cnblogs.com/ningmengcao-ios/p/9578218.html
原文出处:https://www.cnblogs.com/benxiaokang/p/ios-uiwebview-he-wkwebview-de-cookie-huo-qu-she-zh.html
今天关于禁用 iOS WKWebView 中的日期操作的分享就到这里,希望大家有所收获,若想了解更多关于BAWKWebView BAWKWebView 分类封装 WKWebView、iOS - WKWebView那些坑、ios uiwebview wkwebview注意点小记、iOS UIWebView 和 WKWebView 的 cookie 获取,设置,删除等相关知识,可以在本站进行查询。
本文标签: