iOS之WKWebView封装

最近在开发的时候遇到一个麻烦的事,iOS客户端开发使用了webview,但是发现共性问题了之后,就得每个项目都要去改动,然后我就封装了个webview,准备以后得iOS客户端项目统一使用这个类,出现问题了也好处理。

首先,这个封装是针对WKWebView的封装,我们现在使用的也是此webview。源码如下,也欢迎大家留言,我来完善。

@interface LLWKWebView : UIView

//web的title,时时更新
@property (nonatomic, copy  )   NSString *titleName;

//加载的H5的链接
@property (nonatomic, copy  )   NSString *url;

//自定义的UA,默认为""
@property (nonatomic, copy  )   NSString *userAgent;

//url的requestHeader里的内容,string形式的key和value,默认@{}
@property (nonatomic, copy  )   NSDictionary *headerParams;

//message.name,message.body
@property (nonatomic, copy  )   void(^jsActionBlock)(NSString *name,id body);

//jsArray:ScriptMessageHandler方法名
- (instancetype)initWithConfig:(NSArray *)jsArray frame:(CGRect)frame;

//加载url
- (void)startLoadUrl;

//刷新界面
- (void)wkRefresh;

//返回上一个界面---popViewController
- (void)wkPopViewController;

//返回web的history---[wkWebView goBack];
- (void)wkGoWebHistory;

//返回主界面---popToRootViewController
- (void)wkPopRootViewController;

@end
@interface LLWKWebView()<WKNavigationDelegate,WKScriptMessageHandler>
{
    NSMutableURLRequest *webRequest;
    WKWebViewConfiguration *wkConfig;
    
    NSArray *configArray;
    NSMutableDictionary *headers;
}

@property (nonatomic, copy  )   WKWebView *wkWebView;

@property (nonatomic, copy  )   UIActivityIndicatorView *loadingView;

@end

@implementation LLWKWebView

- (void)dealloc
{
    [wkConfig.userContentController removeAllUserScripts];
    _wkWebView.navigationDelegate = nil;
}

#pragma -mark init
- (instancetype)initWithConfig:(NSArray *)jsArray frame:(CGRect)frame
{
    self = [super init];
    if (self) {
        self.frame = frame;
        configArray = jsArray;
        headers = [NSMutableDictionary dictionary];
        
        _titleName = @"";
        _url = @"";
        _userAgent = @"";
        wkConfig = [[WKWebViewConfiguration alloc] init];
        _loadingView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        
        [self initWeb:frame];
    }
    return self;
}

- (void)initWeb:(CGRect)frame
{
    WKUserContentController *userContentController = [[WKUserContentController alloc] init];
    for (NSString *jsName in configArray) {
        [userContentController addScriptMessageHandler:self name:AI_STR_DEFAULT(jsName)];
    }
    wkConfig.userContentController = userContentController;
    
    _wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) configuration:wkConfig];
    _wkWebView.navigationDelegate = self;
    [self addSubview:_wkWebView];
    
    _loadingView.center = _wkWebView.center;
    [self addSubview:_loadingView];
}

#pragma -mark setter
- (void)setUserAgent:(NSString *)userAgent
{
    _userAgent = userAgent;
    if (@available(iOS 12.0, *)){
        NSString *baseAgent = [_wkWebView valueForKey:@"applicationNameForUserAgent"];
        NSString *userAgent = [NSString stringWithFormat:@"%@ %@",baseAgent,_userAgent];
        [_wkWebView setValue:userAgent forKey:@"applicationNameForUserAgent"];
    }
    [_wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSString *newUA = [NSString stringWithFormat:@"%@ %@",result,self->_userAgent];
        self->_wkWebView.customUserAgent = newUA;
    }];
}

- (void)setUrl:(NSString *)url
{
    NSString *urlString = [url stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    urlString = [urlString stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    urlString = [urlString stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    _url = urlString;
}

- (void)setHeaderParams:(NSDictionary *)headerParams
{
    _headerParams = headerParams;
    [headers setValuesForKeysWithDictionary:_headerParams];
}

#pragma mark - webView加载
- (void)startLoadUrl
{
    if (_url && _url.length > 0)
    {
        webRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20];
        NSArray *headerKeys = headers.allKeys;
        for (NSInteger i=0;i<headerKeys.count;i++) {
            NSString *key = AI_STR_DEFAULT(headerKeys[i]);
            NSString *value = AI_STR_DEFAULT(headers[key]);
            [webRequest setValue:value forHTTPHeaderField:key];
        }
        [_wkWebView loadRequest:webRequest];
    }
}

- (void)wkRefresh
{
    [self startLoadUrl];
}

#pragma mark - WKWebview
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
    [self startLoading];
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
    [self stopLoding];
}

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
    [self stopLoding];
    if(error.code == NSURLErrorCancelled)  {
        return;
    }
    if (error.code == NSURLErrorUnsupportedURL) {
        return;
    }
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    [self stopLoding];
    self.titleName = webView.title;
}

#pragma mark - 加载JS处理
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    if (_jsActionBlock) {
        _jsActionBlock(AI_STR_DEFAULT(message.name),message.body);
    }
}

#pragma -mark 方法
- (void)startLoading
{
    [_loadingView startAnimating];
    _loadingView.hidden = NO;
}

- (void)stopLoding
{
    [_loadingView stopAnimating];
    _loadingView.hidden = YES;
}

- (UIViewController *)findViewController
{
    id target=self;
    while (target) {
        target = ((UIResponder *)target).nextResponder;
        if ([target isKindOfClass:[UIViewController class]])
            break;
    }
    return target;
}

- (void)wkPopViewController{
    [[self findViewController].navigationController popViewControllerAnimated:YES];
}

- (void)wkPopRootViewController{
    [[self findViewController].navigationController popToRootViewControllerAnimated:YES];
}

- (void)wkGoWebHistory{
    if ([_wkWebView canGoBack]) {
        [_wkWebView goBack];
    }
    else{
        [self wkPopViewController];
    }
}

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,623评论 4 59
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,037评论 1 32
  • [清]曹寅 紫雪冥蒙楝花老,蛙鸣厅事多青草; 庐江太守访故人,建康并驾能倾倒。 两家门第皆列戟,中年领郡稍迟早; ...
    Fwx烟雨倾城阅读 1,162评论 0 1
  • 世界美味 En la mañana de 17 de enero, en la sede de la Embaja...
    勇行者阅读 333评论 0 0
  • 昨天[童府妈妈学社]的群应大家的呼声,从免费变成了收费群,缘起是因为我们一位工作了十多年刚刚离开自己高管的工作岗位...
    王五月阅读 443评论 0 1