知乎日报前三周总结)
- 首页
- 网络申请
- 上拉刷新
- 详情页
- WKWebView
- 左右滑动
- 首页和详情页的数据传输
- 总结
首页
上述图片是笔者首页的完成效果,首页中并没有特别难的部分,主要的难点就是上拉刷新以及网络申请的问题,最上方使用了一个无线轮播视图,这里的实现并不是很难,主要的问题还是关于网络申请的部分。
网络申请
网络申请笔者这里采用的是AFNetWroking以及YYModel完成的网络申请,这些内容才之前的博客中都有过讲解,这里就不多进行赘述,这里主要还面临的问题就是网络异步的问题,这里笔者使用GCD来解决这个问题,但是GCD的原理等笔者还没有学习,这里先使用来解决网络异步的问题。
- (void)loadImages:(long) a {// 使用 dispatch_group 来等待所有图片加载完成dispatch_group_t imageLoadGroup = dispatch_group_create();NSMutableArray* arrimage = [NSMutableArray array];for (NSDictionary *dic in self->_arrStories[a]) {NSArray* arr = dic[@"images"];NSURL *imageurl = [NSURL URLWithString:arr[0]];UIImageView *iview = [[UIImageView alloc] init];dispatch_group_enter(imageLoadGroup); // 进入组[iview sd_setImageWithURL:imageurlplaceholderImage:[UIImage imageNamed:@"placeholder.png"]options:SDWebImageRefreshCachedcompleted:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {if (error) {NSLog(@"加载图片失败: %@", error.localizedDescription);} else {NSLog(@"图片加载成功");}dispatch_group_leave(imageLoadGroup); // 离开组}];[arrimage addObject:iview];}[self->_arr_image addObject:arrimage];// 在所有图片加载完成后设置主视图dispatch_group_notify(imageLoadGroup, dispatch_get_main_queue(), ^{[self loadtopImages]; // 设置主视图});
}- (void)loadtopImages {// 使用 dispatch_group 来等待所有图片加载完成dispatch_group_t imageLoadGroup = dispatch_group_create();for (NSDictionary *dic in self->_arr_top_stories) {NSString* arr = dic[@"image"];NSLog(@"%@", arr);NSURL *imageurl = [NSURL URLWithString:arr];UIImageView *iview = [[UIImageView alloc] init];dispatch_group_enter(imageLoadGroup); // 进入组[iview sd_setImageWithURL:imageurlplaceholderImage:[UIImage imageNamed:@"placeholder.png"]options:SDWebImageRefreshCachedcompleted:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {if (error) {NSLog(@"加载图片失败: %@", error.localizedDescription);} else {NSLog(@"图片加载成功");}dispatch_group_leave(imageLoadGroup); // 离开组}];[self->_arr_topimage addObject:iview];}// 在所有图片加载完成后设置主视图dispatch_group_notify(imageLoadGroup, dispatch_get_main_queue(), ^{[self setupMainView]; // 设置主视图});
}
根据上述代码可以看出,笔者这里采用一个请求嵌套一个请求的方法,避免最后更新主视图时出现空数组的情况,导致报错。
上拉刷新
这里我通过使用滚动视图的协议来判断是否tableview已经滑动到了底端,如果已经滑动到了底端,就进行网络申请,获取前一天的数据,这样就达到了一个上拉刷新的效果。
CGFloat y = scrollView.contentOffset.y;CGFloat contentHeight = scrollView.contentSize.height;CGFloat height = scrollView.bounds.size.height;if (y + height >= contentHeight + 10) {[self Gaindate];}-(void) Gaindate {if(self.action)return;self.action = YES;[self.mainview.active startAnimating];NSString *strweb = @"https://news-at.zhihu.com/api/4/news/before/";// 使用 stringByAppendingFormat 创建一个新的字符串strweb = [strweb stringByAppendingFormat:@"%@", [self->_date lastObject]];NSLog(@"%@", strweb);id manager = [Manager shareManager];[manager URLString:strweb NetWorkWithData:^(ModelShuju * _Nonnull mainModel) {NSDictionary *dic = [mainModel yy_modelToJSONObject];NSArray *arr = dic[@"stories"];[self.date addObject:dic[@"date"]];// 在主线程中更新 UIdispatch_async(dispatch_get_main_queue(), ^{[self->_arrStories addObject:arr];[self loadImages1:(self->_arrStories.count - 1)];// 加载图片[self getURL:(self->_arrStories.count - 1)];});} error:^(NSError * _Nonnull error) {NSLog(@"error:%@", error.localizedDescription);}];
}
通过这两个函数就可以刷新前一天的数据。
详情页
上图即笔者的详情页,这个页面中主要的问题就是左右滑动时进行对webView的申请,还有就是对于首页和详情页之间的相互传递信息,当详情页刷新到一个没有出现的信息时,需要使用传值将信息传递回首页,同步更新内容。
WKWebView
WKWebView使用时需要添加头文件:
#import <WebKit/WebKit.h>
而后使用其实比较简单:
NSString *urlString = _strurl[_count];NSURL *url = [NSURL URLWithString:urlString];NSURLRequest *request = [NSURLRequest requestWithURL:url];[_webview loadRequest:request];
如上所示,就可以加载出webview了。
左右滑动
笔者这里左右滑动的逻辑上还存在一点问题,无法一次滑动多个页面跳过中间的进行webview的申请,后期还需要对这里进行一个升级,这里先展示笔者现有的逻辑。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {if (fabs(scrollView.contentOffset.x - self.lastContentOffset.x) > fabs(scrollView.contentOffset.y - self.lastContentOffset.y)) {scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, self.lastContentOffset.y);} else {self.lastContentOffset = scrollView.contentOffset; // 更新位置}CGFloat widthNow = self.mainview.scroll.contentOffset.x;CGFloat widthbegin = self.count * 393;CGFloat width = self.mainview.scroll.contentSize.width;NSInteger cha = width - widthNow;NSInteger cha1 = widthbegin - widthNow;
// NSLog(@"%ld", (long)cha1);if(cha == 393 && !_Right) {NSLog(@"开始申请");_Right = YES;self.mainview.scroll.contentSize = CGSizeMake(width + 393, 719);_webview = [[WKWebView alloc] initWithFrame:CGRectMake(widthNow, 0, 393, 719)];_webview.navigationDelegate = self;if(_countright < _strurl.count) {[self gainextra:_countright];NSString *urlString = _strurl[_countright];_countright++;NSLog(@"URL String: %@", urlString);[self gainWebview:urlString];} else {NSLog(@"重新申请");[self gaindate];}}if(cha1 == 393 && !_Right) {NSLog(@"开始申请");_Right = YES;_webview = [[WKWebView alloc] initWithFrame:CGRectMake(widthNow, 0, 393, 719)];_webview.navigationDelegate = self;[self gainextra:_countleft];NSString *urlString = _strurl[_countleft];_count--;_countleft--;NSLog(@"URL String: %@", urlString);[self gainWebview:urlString];}
}
笔者这里通过判断滑动的位置来进行网络申请,申请webview展示在滚动视图上,但是由于我的限制,不可以跳过中间的页面进行申请后面的页面,后面会更改逻辑上的问题,从而使得更加完善。
首页和详情页的数据传输
这里主要需要传输的就是当我在详情页获取到新的一天的数据,即首页中未刷新的前一天的数据时,需要将这个数据传输会首页,让首页进行一个tableview的刷新,从而使得更加的流畅和合理。其实对于首页传输到详情页而言,则更为简单,笔者这里直接使用了属性传值的方法,就不过多进行赘述了。
笔者这里使用了通知传值的方法,当我获得到新的一天的数据时,直接传递回首页。
NSDictionary* dictionary = @{@"stories":[self->_arrStories lastObject],@"date":[self->_arrdate lastObject]};[[NSNotificationCenter defaultCenter] postNotificationName:@"inform" object:nil userInfo:dictionary];
首页中:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(receiveNoticed:) name:@"inform" object:nil];}
- (void)receiveNoticed:(NSNotification*)sender {[_arrStories addObject:sender.userInfo[@"stories"]];[_date addObject:sender.userInfo[@"date"]];[self loadImages111:(_arrStories.count - 1)];}
这样就可以相互传递信息,避免了两个页面中数据不同步导致逻辑不甚合理的问题了。
总结
后面的内容笔者还在写,对于评论区的展开功能还没有写完,仅申请到了数据,还有收藏的知识点没有学习,后面的内容笔者后期还会总结,这次就先总结这么多内容。