iOS wkwebview怎么写localStorage

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS wkwebview怎么写localStorage相关的知识,希望对你有一定的参考价值。

参考技术A ios中WKWebView,存在首次加载h5页面,h5页面中的js就拿不到localstorage了。

WKWebView localStorage 缓存很严重

html5在客户端存储数据的方式:cookie , localStorage, sessionStorage
cookie:只能存储少量的数据, 常用来存储账号密码等
localStorage : 没有时间限制的数据存储
sessionStorage : 针对一个 session 的数据存储, 当网页关闭时,数据也会被删除。

1.WKWebView设置localStorage
NSString * userContent = [NSString stringWithFormat:@""token": "%@", "userId": %@", @"a1cd4a59-974f-44ab-b264-46400f26c849", @"89"];
// 设置localStorage
NSString *jsString = [NSString stringWithFormat:@"localStorage.setItem('userContent', '%@')", userContent];
// 移除localStorage
// NSString *jsString = @"localStorage.removeItem('userContent')";
// 获取localStorage
// NSString *jsString = @"localStorage.getItem('userContent')";
[self.webView evaluatejavascript:jsString completionHandler:nil];

NSString * userContent = @""name": "Tom", "age": 10"];
// 设置localStorage
NSString *jsString = [NSString stringWithFormat:@"localStorage.setItem('userContent', '%@')", userContent];
// 移除localStorage
// NSString *jsString = @"localStorage.removeItem('userContent')";
// 获取localStorage
// NSString *jsString = @"localStorage.getItem('userContent')";
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
//清理掉所有的localStorage数据
//NSString *clearString = @"localStorage.clear()";

iOS wkwebview localstorage数据处理

WKWebView 在内存占用上优化的很多。但是在实践中发现bug:localstorage信息不一致。

A页面和B页面都存在 一个WKWebView。 在B页面使用localstorage保存信息。 回到A页面取不到最新的数据。

原因:

https://developer.apple.com/reference/webkit/wkwebviewconfiguration 中有个属性 processPool,描述是:The process pool from which to obtain the view’s Web Content process.

解决方法:

把config中的processPool变为单例共享



设置webview的配置 config.processPool = [NYWKWebView singleWkProcessPool];

在查询资料的过程中,发现了很多Local Storage的缺陷,有一篇关于Local Storage的 论文 可以参考。有以下几点:

webview 和 iframe 有什么区别?

webview是网页的原生载体,用于在原生环境中加载一个页面,iframe是网页的html载体,用于在网页中加载一个页面

iOS WKWebView长按自定义菜单功能

参考技术A 最近做需求时碰到了要webview自定义MenuItem的功能,系统自带的菜单栏显示很多item用不着

以前做过类似的需求,但是搞完后发现在iOS15系统上显示不对,还是会有系统的copy等,最终通过runtime交换wkwebview的系统方法解决。

解决方法
1、自定义一个wkwebview的钩子hook类,用自定义的方法替换系统的方法
@implementation WELWKWebViewMenuHook

+ (void)load

    staticdispatch_once_tonceToken;

    dispatch_once(&onceToken, ^

        Method  m =class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"canPerformAction:withSender:"));

        class_addMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"), (IMP)wel_canPerformAction, method_getTypeEncoding(m));

        Method m1 = class_getInstanceMethod(NSClassFromString(@"WKContentView"),NSSelectorFromString(@"canPerformAction:withSender:"));

        Method m2 = class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"));

        method_exchangeImplementations(m1,m2);

        Method  M =class_getInstanceMethod(NSClassFromString(@"WKWebView"), NSSelectorFromString(@"canPerformAction:withSender:"));

        class_addMethod(NSClassFromString(@"WKWebView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"), (IMP)wel_canPerformAction, method_getTypeEncoding(M));

        Method M1 = class_getInstanceMethod(NSClassFromString(@"WKWebView"),NSSelectorFromString(@"canPerformAction:withSender:"));

        Method M2 = class_getInstanceMethod(NSClassFromString(@"WKWebView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"));

        method_exchangeImplementations(M1,M2);

    );



上面方法实现了把系统的WKWebView和WKContentView中响应item的方法替换为自定义方法wel_canPerformAction,然后在wel_canPerformAction方法中实现
BOOLwel_canPerformAction(idself,  SEL_cmd,SELarg1,idarg2)

    NSString*actionString =NSStringFromSelector(arg1);

    BOOL isShowQyMenuItem = [[[NSUserDefaults standardUserDefaults] objectForKey:@"KIsShowQYMenuItem"] boolValue];//bool值来控制是否需要显示自定义的menuItem

    if([actionStringisEqualToString:@"qy_addNotes:"] || [actionStringisEqualToString:@"qy_collection:"] || [actionStringisEqualToString:@"qy_share:"] || [actionStringisEqualToString:@"qy_copy:"])

        returnisShowQyMenuItem;

    else

        return!isShowQyMenuItem;

   


此方法返回yes就显示对应的item,返回no就不显示,所以在此方法中根据自定义的方法名字来显示想要的item,hook类中就实现这两个方法就ok,接下来是在自定义的wkwebview中实现方法。
2、自定义继承WKWebView的类,实现每个item对应的方法,举个例子,

- (void)qy_addNotes:(UIMenuController *)menu



    [self evaluateJavaScript:@"window.getSelection().toString()" completionHandler:^(id _Nullable content, NSError * _Nullable error)

        NSString*selectContent = (NSString*)content;

        NSLog(@"选中-----%@", selectContent);

        if(self.noteBlock)

            self.noteBlock(selectContent);

       

    ];



其中window.getSelection().toString()是获取当前选中的内容,然后通过block或者代理就可以把item方法传递到继承这个wkwebview的子类中来做相应的操作了。

最终解决了问题

最后附上demo: https://github.com/726491400/CustomMenuItem
感谢大佬的文章: https://www.jianshu.com/p/dd7452d3d123

以上是关于iOS wkwebview怎么写localStorage的主要内容,如果未能解决你的问题,请参考以下文章

WKWebView 底部视图显示不全

iOS-WebView(WKWebView)进度条

【iOS】WKWebView使用Cookies遇到的坑

IOS Swift WkWebview如何屏蔽长按

网页截长图分享和保存iOS

[iOS开发]WKWebView加载JS