【iOS】知乎日报前三周总结

知乎日报前三周总结)

首页

上述图片是笔者首页的完成效果,首页中并没有特别难的部分,主要的难点就是上拉刷新以及网络申请的问题,最上方使用了一个无线轮播视图,这里的实现并不是很难,主要的问题还是关于网络申请的部分。

网络申请

网络申请笔者这里采用的是AFNetWroking以及YYModel完成的网络申请,这些内容才之前的博客中都有过讲解,这里就不多进行赘述,这里主要还面临的问题就是网络异步的问题,这里笔者使用GCD来解决这个问题,但是GCD的原理等笔者还没有学习,这里先使用来解决网络异步的问题。

objectivec 复制代码
- (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:imageurl
                placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                         options:SDWebImageRefreshCached
                       completed:^(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:imageurl
                placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                         options:SDWebImageRefreshCached
                       completed:^(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已经滑动到了底端,如果已经滑动到了底端,就进行网络申请,获取前一天的数据,这样就达到了一个上拉刷新的效果。

objectivec 复制代码
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"]];
        
        // 在主线程中更新 UI
        dispatch_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使用时需要添加头文件:

objectivec 复制代码
#import <WebKit/WebKit.h>

而后使用其实比较简单:

objectivec 复制代码
    NSString *urlString = _strurl[_count];
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [_webview loadRequest:request];

如上所示,就可以加载出webview了。

左右滑动

笔者这里左右滑动的逻辑上还存在一点问题,无法一次滑动多个页面跳过中间的进行webview的申请,后期还需要对这里进行一个升级,这里先展示笔者现有的逻辑。

objectivec 复制代码
- (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的刷新,从而使得更加的流畅和合理。其实对于首页传输到详情页而言,则更为简单,笔者这里直接使用了属性传值的方法,就不过多进行赘述了。

笔者这里使用了通知传值的方法,当我获得到新的一天的数据时,直接传递回首页。

objectivec 复制代码
NSDictionary* dictionary = @{@"stories":[self->_arrStories lastObject],@"date":[self->_arrdate lastObject]};
            [[NSNotificationCenter defaultCenter] postNotificationName:@"inform" object:nil userInfo:dictionary];

首页中:

objectivec 复制代码
[[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)];
    
}

这样就可以相互传递信息,避免了两个页面中数据不同步导致逻辑不甚合理的问题了。

总结

后面的内容笔者还在写,对于评论区的展开功能还没有写完,仅申请到了数据,还有收藏的知识点没有学习,后面的内容笔者后期还会总结,这次就先总结这么多内容。

相关推荐
程序猿online40 分钟前
nvm安装使用,控制node版本
开发语言·前端·学习
lijiachang0307181 小时前
设计模式(一):单例模式
c++·笔记·学习·程序人生·单例模式·设计模式·大学生
Kaelinda1 小时前
iOS开发代码块-OC版
ios·xcode·oc
Hacker_Oldv1 小时前
网络安全攻防学习平台 - 基础关
网络·学习·web安全
胡西风_foxww2 小时前
【ES6复习笔记】let 和 const 命令(1)
笔记·学习·es6·const·let
网络安全(king)2 小时前
网络安全之接入控制
网络·学习·安全·web安全
PP东4 小时前
ES学习class类用法(十一)
javascript·学习
百流6 小时前
scala基础学习_运算符
开发语言·学习·scala