UIWebView 使用- 缓存 - 写cookie - JS - OC 交互 - 自动登陆

1. 使用



- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = @"查看";

    [self addWebView];
}
- (void)addWebView
{
    _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - 64)];

    /// 这是默认的策略 
    [self loadDataWithProtocol];
    
    // 如果不想要webView 的回弹效果
    _webView.scrollView.bounces = NO;
    _webView.scalesPageToFit = YES ;
    _webView.delegate = self;
    // UIWebView 滚动的比较慢,这里设置为正常速度
    self.webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
    
    [self.view addSubview:_webView];

}

2. 加载

2.1 带缓存加载 使用协议缓存, 需要 web 服务器支持. 默认策略


- (void)loadDataWithProtocol
{

    NSURL *url = [NSURL URLWithString:@"http://m.XXXX.net"];
    
    [NSURLRequest requestWithURL:url];
    
    NSURLRequest *urlReq = [NSURLRequest requestWithURL:url
                                            cachePolicy:NSURLRequestUseProtocolCachePolicy
                                        timeoutInterval:60.f];
    
    [self.webView loadRequest:urlReq];

// 等同于
//[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://m.XXXX.net"]]];
}

2.2 带缓存加载 新安装app 无缓存 会崩溃 (无用, 仅做记录)


- (void)loadDataUsingCache
{

    NSURL *url = [NSURL URLWithString:@"http://www.XXXX.com"];
    
    NSURLRequest *urlReq = [NSURLRequest requestWithURL:url
                                            cachePolicy:NSURLRequestReturnCacheDataDontLoad
                                        timeoutInterval:10.f];
    
    [_webView loadRequest:urlReq];
    
    
}

2.3 不带缓存加载 (无用, 仅做记录)

- (void)loadDataNoUsingCache
{
    
    NSURL *url = [NSURL URLWithString:@"http://www.XXXX.com"];
    NSURLRequest *urlReq = [NSURLRequest requestWithURL:url
                                            cachePolicy:NSURLRequestReloadIgnoringCacheData
                                        timeoutInterval:20.0];
    [self.webView loadRequest:urlReq];
}

2.4 清除所有缓存 (无用, 仅做记录)

- (void)clearAllCache
{
    // remove cache rsp
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
}


3. 写cookie

3.1 要求( 仿照安卓的代码)

//写cookie, 页面根据cookie判断当前页面是在 "我" 还是 "查看" 里
cookieManager.setCookie(App.htmlurl, "wxTabIndex=0"); //"我" 界面为1, "查看" 为0

3.1 解决方案


/// 这里的 webViewDidFinishLoad内方法删除了其他的内容, 方便说明
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    
    [self changeCookie];
}


-(void)changeCookie
{
    NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
    [cookieProperties setObject:@"App.htmlurl" forKey:NSHTTPCookieName];
    [cookieProperties setObject:@"wxTabIndex=0" forKey:NSHTTPCookieValue];

    [cookieProperties setObject:@"www.XXXX.com" forKey:NSHTTPCookieDomain];
    [cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
    [cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
    
    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}


3.2 附注: 删除Cookie 和 查找Cookie (我没用到)

- (void)deleteCookie
{
    NSLog(@"============删除cookie===============");
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    
    //删除cookie
    for (NSHTTPCookie *tempCookie in cookies) {
        [cookieStorage deleteCookie:tempCookie];
    }
    
    //把cookie打印出来,检测是否已经删除
    NSArray *cookiesAfterDelete = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    for (NSHTTPCookie *tempCookie in cookiesAfterDelete) {
        NSLog(@"cookieAfterDelete: %@", tempCookie);
    }
    NSLog(@"\n");
}


- (void)searchCoookie
{
    //获取cookie
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    for (NSHTTPCookie *tempCookie in cookies) {
        //打印获得的cookie
        NSLog(@"getCookie: %@", tempCookie);
    }
}

4. OC调用JS

4.1 要求1

每次切换到 "查看" 调用函数:
webView.loadUrl("javascript:XXXXXX.App.clickDevice(1)"); //页面处理需要

4.1 解决方案点击Tabbar的时候操作

- (void)tabBarSeleted:(NSNotification *)notification
{

    [_webView stringByEvaluatingJavaScriptFromString:@"javascript:XXXXXX.App.clickDevice(1)"];
}

5. JS调用OC

5.1 创建 需要注册到JS的模型的类

JsObjCModel.h


#import <Foundation/Foundation.h>


#import <JavaScriptCore/JavaScriptCore.h>

@protocol JavaScriptObjectiveCDelegate <JSExport>
/// 网页调用这个方法 检测app蓝牙是否连接打印机
- (void)PrintConnect;
/// 如果连接, 网页会调用这个方法
- (void)PrintData:(NSString *)str;


@end

// 此模型用于注入JS的模型,这样就可以通过模型来调用方法。
@interface HYBJsObjCModel : NSObject <JavaScriptObjectiveCDelegate>

@property (nonatomic, weak) JSContext *jsContext;
@property (nonatomic, weak) UIWebView *webView;

@end

JsObjCModel.m


#import "JsObjCModel.h"




@implementation JsObjCModel

- (void)PrintConnect
{
    NSLog(@"JS调用了OC的方法,检测打印机");
    
    BOOL isConnection = [[BluetoothPrinterManager sharedManager] checkPrinterIsConnection];
    if (isConnection) {
  // JS调用后OC后,又通过OC调用JS 这里只是简单使用
        [_webView stringByEvaluatingJavaScriptFromString:@"javascript:XXXX.App.setPrinterConnOk()"];
    }

}

- (void)PrintData:(NSString *)str
{
    NSLog(@"JS调用了OC的方法,PrintData-- %@", str);
    
    [[BluetoothPrinterManager sharedManager] startPrintString:[NSString stringWithFormat:@"%@", str]];
    //    // JS调用后OC后,又通过OC调用JS,但是这个是没有传参数的
//        JSValue *jsFunc = self.jsContext[@"jsFunc"];
//        [jsFunc callWithArguments:nil];
}


使用


@interface DAViewController ()<UIWebViewDelegate, UIGestureRecognizerDelegate>


@property (nonatomic) UIWebView *webView;
@property (nonatomic, strong) JSContext *jsContext;


//返回按钮
@property (nonatomic, strong) UIBarButtonItem *webBackItem;

@property (nonatomic, strong) UIBarButtonItem *rightButton;


@end

创建



- (void)webViewDidFinishLoad:(UIWebView *)webView
{
  
    /// 加载网页完毕 再注入模型 (注入太早可能网页不会响应)
     [self injectedObject:webView];
    
}


/// 注入模型
- (void)injectedObject:(UIWebView *)webView
{
   
    self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 通过模型调用方法,这种方式更好些。
    HYBJsObjCModel *model  = [[HYBJsObjCModel alloc] init];
    model.jsContext = self.jsContext;
    model.webView = self.webView;
    self.jsContext[@"java"] = model;

    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
        NSLog(@"异常信息:%@", exceptionValue);
    };
}


6. 显示网页返回按钮


/// 网页加载完毕 判断 canGoBack
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    // 去掉网页 footer
    [webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('content-footer').remove();"];

    //获取当前页面的title 修改导航栏标题
    NSString *title= [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    [self.navigationItem setTitle:title];

        
    //判断是否有上一层H5页面
    if ([webView canGoBack]) {
        //同时设置返回按钮和关闭按钮为导航栏左边的按钮
        self.navigationItem.leftBarButtonItems = @[self.webBackItem];
    } else {
        self.navigationItem.leftBarButtonItems = @[];
    }
}

/// 懒加载
- (UIBarButtonItem *)webBackItem
{
    if (!_webBackItem) {
        _webBackItem = [[UIBarButtonItem alloc] init];
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        //这是一张“<”的图片,可以让美工给切一张
        UIImage *image = [UIImage imageNamed:@"barbuttonicon_back"];
        [btn setImage:image forState:UIControlStateNormal];
        [btn setTitle:@"" forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(backNative) forControlEvents:UIControlEventTouchUpInside];
        [btn.titleLabel setFont:[UIFont systemFontOfSize:17]];
        [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        //字体的多少为btn的大小
        [btn sizeToFit];
        //左对齐
        btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        //让返回按钮内容继续向左边偏移15,如果不设置的话,就会发现返回按钮离屏幕的左边的距离有点儿大,不美观
//        btn.contentEdgeInsets = UIEdgeInsetsMake(0, -15, 0, 0);
        btn.frame = CGRectMake(0, 0, 40, 40);
        _webBackItem.customView = btn;
    }
    return _webBackItem;
}

//点击返回的方法
- (void)backNative
{
    //判断是否有上一层H5页面
    if ([self.webView canGoBack]) {
        //如果有则返回
        [self.webView goBack];
        
    } else {
        [self closeNative];
    }
}


7. 一个网页登陆 刷新另外一个网页也登陆

tabbar 有三个按钮, 其中两个按钮都是网页webView. 一个网页登陆以后, 如果点击另外一个Tabbar, 也要让该webView登陆.并跳转到个人页面.
  • 1, 在 AppDelegate 新建个属性 isLoginWeb用来标记 是否已经登陆网页

  • 2, 如果一个webView登陆以后 就标记 这个 isLoginWeb为YES
    证明app内有人进行了登陆操作并登陆成功.

  • 3, 并在自身的 VC内也新建个属性 isLoginWeb 用来标记 自身是否已经登陆,
    因为系统内其他VC已经登陆网页,并不代表自身Vc已经登陆网页.
    登陆成功以后,也要把这个属性设置为YES

  • 4, 这个属性的 标记 肯定是在 webViewDidFinishLoad来判断.
    需要根据当前网页的URL 来进行判断. 因为登陆的网页,后缀是 带login 的.

  • 5, 点击Tabbar的时候根据 这两个属性 进行相应的操作

第1步
#import <UIKit/UIKit.h>


@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

/// 是否已经登陆网页
@property (nonatomic, assign) BOOL isLoginWeb;

@end

第2步
@interface DAViewController ()<UIWebViewDelegate, UIGestureRecognizerDelegate>


@property (nonatomic) UIWebView *webView;
@property (nonatomic, strong) JSContext *jsContext;

/// 是否已经登陆网页
@property (nonatomic, assign) BOOL isLoginWeb;

//返回按钮
@property (nonatomic, strong) UIBarButtonItem *webBackItem;

@property (nonatomic, strong) UIBarButtonItem *rightButton;


@end

第3,4步

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
   
    AppDelegate *app = (AppDelegate *)[[UIApplication  sharedApplication] delegate];
    NSString *currentURL = webView.request.URL.absoluteString;
    NSLog(@"currentURL -- %@", currentURL);
    if ([currentURL isEqualToString:@"http://www.XXXX.com/Login"]) {
        app.isLoginWeb = NO;
        self.isLoginWeb = NO;
    } else if ([currentURL isEqualToString:@"http://www.XXXX.com/Home"]  ||[currentURL isEqualToString:@"www.XXXX.com/"]) {
        app.isLoginWeb = YES;
        self.isLoginWeb = YES;
        [_webView stringByEvaluatingJavaScriptFromString:@"javascript:XXXXX.App.clickDevice(1)"];
        
    }  else {
        app.isLoginWeb = YES;
        self.isLoginWeb = YES;
    }
 
}

第5步
- (void)tabBarSeleted:(NSNotification *)notification
{
    AppDelegate *app = (AppDelegate *)[[UIApplication  sharedApplication] delegate];
    
    if (app.isLoginWeb && self.isLoginWeb) {
        // 如果本VC 已经登陆, 就去调用JS函数 (产品需要)
        [_webView stringByEvaluatingJavaScriptFromString:@"javascript:XXXX.App.clickDevice(1)"];
    } else {
        // 如果没有登陆, 就去从缓存中获取,如果缓存已经登陆,会自动登陆, 如果没有登陆,会跳转到登录页面.(这是webView自己做的缓存, 和我无关)
        [self loadDataWithProtocol];
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容