开篇
忽然发现最近也只有值班才能写东西了,中间更新了两篇其他的断了下商城相关的文章,仔细看了看之前觉得干货太少,今天写点实际的吧,闲说少说商城相关的更新今天继续吧,哈哈。前两篇文章:iOS走近商城APP(一) ,iOS走近商城APP(二 购物车常用控件)(今天值班整座大楼一如既往的静悄悄,胆小怪我咯-_-、)。
主要内容
- 使用WKWebView替换Webview
WKWebView的html网页的加载方法
WKWebView显示网页的base页面的封装,点击页面的拦截方法
商品详情页页面的自适应布局 - 商品规格选择框架
基于内容宽度自适应的框架封装,优化之前介绍的第三方框架带来的问题
使用WKWebView替换Webview
在商城中,使用html网页做展示页面,商品详情,活动页面再常见不过,往往有许多,但是
Webview大量使用会存在内存暴增,如果用WKWebView就能大大减少内存,下面就具体介绍一下使用过程,至于WKWebView的原理以及基本的代理这里就不一一列举了,实战出发,哈哈。
- 活动页Webview的替换
签到页面.png
如图我们点击立即签到和立即签钱,会触发不同的点击事件,当然在许多别的页面,我们点击网页上的内容还要跳转到软件本身的界面,我们的怎么处理他呢?在老的Webview中我们遵循UIWebViewDelegate的代理方法,然后处理方式如下
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
}
拦截点击事件,然后再方法中做出处理
NSString* urlString=[[request URL] absoluteString];
NSLog(@"%@",urlString);
NSArray* actionArray=[urlString componentsSeparatedByString:@"-"];
for (NSString* actionStr in actionArray) {
if ([actionStr isEqualToString:@"SignNew.StartSign"]) {//跳转签到页面-action
[webView stopLoading];
[self gotoSignIn];
}else if([actionStr isEqualToString:@"Task.TaskDetail"]){//跳转界面
....代码原理同上
}else if([actionStr isEqualToString:@"Task.TaskList"]){//跳转页面
...代码原理同上
}
原理就是我们截取到点击事件然后根据后台返回的网址进行处理,根据网址中不同的字段跳转到我们想要跳转的页面。
在WKWebView中我们的处理方式如下遵循WKNavigationDelegate代理方法,然后调用方法
#pragma mark - WKWebviewDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
}
在这个方法中进行上述的处理,
NSString *urlString = [navigationAction.request.URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",urlString);
NSArray* actionArray=[urlString componentsSeparatedByString:@"-"];
for (NSString* actionStr in actionArray) {
if ([actionStr isEqualToString:@"SignNew.StartSign"]) {//跳转页面-action
[webView stopLoading];
...
}else if([actionStr isEqualToString:@"Task.TaskDetail"]){//跳转界面
...
}
在处理完跳转逻辑之后记得加上这句代码
decisionHandler(WKNavigationActionPolicyAllow);//允许跳转
下面再放两个加载时的协议方法
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
- WKWebView 商品详情页的自适应布局
如图所示,商品详情的时候我们要根据每个商品详情的不同来对他进行自适应的图文布局,他并不像我们的活动页面那么简单,由于数量比较多,内容不固定因此我们在加载页面的时候要做处理(但是这个一般就不需要做点击交互处理了,哈哈),代码如下
-(WKWebView *)webView{
if (_webView==nil) {
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
[wkUController addUserScript:wkUScript];
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
_webView=[[WKWebView alloc] initWithFrame:CGRectZero configuration:wkWebConfig];
_webView.navigationDelegate = self;
NSURLRequest* request=[NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[_webView loadRequest:request];
}
return _webView;
}
加入一段JS代码对页面进行布局处理。
商品详情的框架封装
在iOS走近商城APP(二 购物车常用控件)文章中,我们介绍了一个商品详情布局的控件,虽然有优点,但是也有他的局限性,因为如果在商品规格比较单一,且长度较短或者固定的时候,是很美观的,但是如果我们想要根据不同的规格长度进行自适应,问题就来了,就出现了商品显示不完整的情况,今天放一个在那个版本的基础上自己又重新封装过的框架吧。效果图如下
详情页布局.png
主要的操作就是优化了根据规格不同,对标签长度以及换行的计算标准更加的趋向于实际应用。
标签的自适应计算主要代码如下(具体可以看git中的源码):
首先创建系统的函数如下,其效果类似于for in遍历
- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
然后再函数中的处理
[_filterData.elements enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Btnx += btnGap;
CGFloat btnWidth = [self WidthWithString:obj fontSize:14 height:BtnHeight];
btnWidth += 10;//让文字两端留出间距
if(btnWidth<minBtnLength)
btnWidth = minBtnLength;
if(btnWidth>maxBtnLength)
btnWidth = maxBtnLength;
if(Btnx + btnWidth > oneLineBtnWidtnLimit)
{
BtnlineNum ++;//长度超出换到下一行
Btnx = btnGap;
}
UIButton *button = [[UIButton alloc] init];
//Y坐标
CGFloat height = btnGapY+ (BtnlineNum*(BtnHeight+btnGapY));
// NSLog(@"Y坐标-------------%f",height);
button.frame = CGRectMake(Btnx, height,
btnWidth,BtnHeight );
//此处省略按钮的具体属性的设置
[button addTarget:self action:@selector(buttonSelected:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
[_buttons addObject:button];
Btnx = button.frame.origin.x + button.frame.size.width + btnGap;
totalHeight = height; //行高为最大的Y坐标加高度
下面放上一个详细举例的gif效果图。
代码传送门GSFilterView,有用的可以点个星哦。
后记
惯例闲扯时间,哈哈,下一篇将写一下runloop在订单列表中的实际应用,获取通讯录手机号码以及iOS9与iOS8下的处理等,督促自己一波哈哈。
网友评论