【iOS】知乎日报第四周总结

【iOS】知乎日报第四周总结

文章目录

前言

这周笔者主要完成了收藏中心的一个内容和一个对于FMDB这个第三方库的一个学习,以及修改了首页获取三个数据顺序混乱的一个问题,以及优化UITableView的内容。

首页获取三个数据混乱的问题

这里首页获取三个数据混乱的原因主要还是因为网络请求的异步回调的问题,这里笔者上网搜索了一下相关内容后面采用了一个NSConditionLock这个类和一个并行队列来解决,这个类是状态锁,这里笔者还不是很清楚原因,这里可以简单介绍一下状态锁的一个内容:

NSConditionLock 用于控制并发任务的执行顺序

  • NSConditionLock 是一种线程同步机制,它允许线程根据特定条件加锁和解锁。在这段代码中,lock 的初始条件为 0。
  • 每个任务都会调用 lockWhenCondition:i,只有当 lock 的当前条件与 i 相等时,任务才会继续执行,否则会阻塞等待。

该部分内容来自chatgpt

这里笔者给出我下滑加载的部分代码:

objc 复制代码
-(void)loadData {
    if (self.loading) {
        return;
    }
    self.loading = YES;
    NSInteger num = [self.dateModel.headString intValue];
    NSString* str = [self.dateModel computingTime:self.dateModel.headString andDay:self.iModel.count - 1];
    NSInteger count = self.iModel.count;
    NSLog(@"%@", str);
    self.iView.tableView.tableFooterView = self.iView.footerView;
    [self.iView.activity startAnimating];
    //dispatch_group_t gruop = dispatch_group_create();
    //[self.iView.activity startAnimating];
    NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:0];
    dispatch_queue_t queue = dispatch_queue_create(@"current", DISPATCH_QUEUE_CONCURRENT);//创建一个并行队列
    for (int i = 0; i < 3; i++) {
        //str = [self.dateModel computingTime:self.dateModel.headString andDay:self.iModel.count - 1];
        //dispatch_group_enter(gruop);
        NSLog(@"执行第%ld个任务", i);
        str = [self.dateModel computingTime:self.dateModel.headString andDay:count - 1 + i];
        NSLog(@"每个任务对应的字符串%@", str);
        [[Manger sharedManger] newDateLoad:^(MainPageModel * _Nonnull model) {
            dispatch_async(queue, ^{
                [lock lockWhenCondition:i];
                [self.iModel addObject:model];
                NSLog(@"%ld", self.iModel.count);
                [lock unlockWithCondition:i + 1];
                if (i == 2) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self.iView.tableView reloadData];
                        [self.iView.activity stopAnimating];
                        self.iView.tableView.tableFooterView = nil;
                        self.loading = NO;
                    });
                }
                NSLog(@"%@", str);
            });
            //dispatch_group_leave(gruop);
        } andNsstring:str];
        //dispatch_group_wait(gruop, DISPATCH_TIME_FOREVER);
    }    
}

FMDB库的一个使用

这里笔者实现收藏中心采用了一个第三方库FMDB这个库来实现的,首先这个库的是用OC来包装sqlite这个小型数据库,然后我们只需要调用她分装好的一个接口就可以了,这里笔者简单介绍一下使用方法,不涉及原理。

创建一个库

创建一个库主要有三种方式来创建,这里笔者介绍的是绝对路径来创建一个数据库。

    1. 绝对路径
    1. 空字符串 @""

会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除。

    1. nil

会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁

在我们对于收藏中心的要求是要存储起来,所以我们采用第一种绝对路径来创建一个数据库

objc 复制代码
- (void)creatDateBase {
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    self.sqlFilePath = [path stringByAppendingPathComponent:@"collectionCenter.sqlite"];
    self.db = [FMDatabase databaseWithPath:_sqlFilePath];
    //[self delete];
    if ([self.db open]) {
        NSLog(@"load success");
    } else {
        NSLog(@"error");
    }
}

添加数据

对于数据库而言我们永远只用在库的最后添加一个数据就可以了,这里采用的是一个INSERT语句

下面给出相关的一个代码:

objc 复制代码
-(void)insertData {
    NSString* sqlInsert = @"INSERT INTO  collectionCenter (webPageId, webPageTitle, webImageURL, likes, star) VALUES (?, ?, ?, ?, ?)";
    if ([[DataBaseManger ShareDateBaseManger].db open]) {
        BOOL flag = [[DataBaseManger ShareDateBaseManger].db executeUpdate:sqlInsert, self.webPageId, self.titile, self.imageUrl, @(self.selectLike), @(self.selectStar)];
        if (flag) {
            NSLog(@"success");
        } else {
            NSLog(@"error");
        }
    }
    
}

删除数据

删除数据的语句是DELETE,我们只要知道有一个属性与我们查找的相同就可以进行一个删除的操作。

objc 复制代码
-(void)deleteData {
    NSString* sqlDelete = @"delete from collectionCenter where (webPageId) = (?) and (webPageTitle) = (?) and (webImageURL) = (?) and (likes) = (?) and (star) = (?)";
    if ([[DataBaseManger ShareDateBaseManger].db open]) {
        BOOL flag = [[DataBaseManger ShareDateBaseManger].db executeUpdate:sqlDelete, self.webPageId, self.titile, self.imageUrl, self.selectLike, self.selectStar];
        if (flag) {
            NSLog(@"删除数据成功");
        } else {
            NSLog(@"删除数据失败");
        }
    } else {
        NSLog(@"打开数据库失败");
    }
}

修改数据

修改数据的语句是一个update其实他和删除语句的大致类似,也是只要有一个属性和我们查找的内容相同就可以了,然后我们修改对应的一个属性值就可以了。

objc 复制代码
-(void)changeData {
    NSString* sqlDelete = @"update collectionCenter set (star) = (?) where (webPageId) = (?)";
    if ([[DataBaseManger ShareDateBaseManger].db open]) {
        BOOL flag = [[DataBaseManger ShareDateBaseManger].db executeUpdate:sqlDelete, @(self.selectStar), self.webPageId];
        if (flag) {
            NSLog(@"修改数据成功");
        } else {
            NSLog(@"修改数据失败");
        }
    } else {
        NSLog(@"打开数据库失败");
    }
}

以上代码就可以实现一个收藏中心的内容,我们只需要在详情页点击按钮之后进行一个数据内容的一个添加就可以了,添加的web的一个pageId和他的titile来对于数据进行一个判断就可以了,将点过赞和收藏过的页面都进行一个记录,然后下一次点击的时候在数据库中进行一个检索,如果点击过就设置一个对应的button的一个选中。

缓存高度数组

在评论区中因为采用的是一个自适应行高,当数据量太大时候会出现一个问题,就是每一个cell的height都要进行一次重复的运算,导致了很大程度上的一个性能开销,所以我们需要采用一个缓存高度数组的一个手段来解决,我们把加载过的cell高度全部存储在高度数组中,然后下一次使用的时候就到缓存过的高度数组中去获取,这样来减小一个性能上的一个开销。

objc 复制代码
-(NSMutableArray *)heightAry {
    if (_heightAry == nil) {
        _heightAry = [NSMutableArray array];
        [_heightAry addObject:[NSMutableDictionary dictionary]];
        [_heightAry addObject:[NSMutableDictionary dictionary]];
    }
    return _heightAry;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (self.heightAry[indexPath.section][@(indexPath.row)] ) {
        NSLog(@"%ld %ld 第几行第几列",indexPath.section, indexPath.row);
        return [self.heightAry[indexPath.section][@(indexPath.row)] doubleValue];
    } else {
        return UITableViewAutomaticDimension;
    }
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (!self.heightAry[indexPath.section][@(indexPath.row)] ) {
        NSLog(@"这%ld行没有存储过的一个高度", indexPath.row);
        id height = [NSNumber numberWithDouble:cell.frame.size.height];
        self.heightAry[indexPath.section][@(indexPath.row)] = height;
    } else {
        NSLog(@"这%ld行曾今存储过的一个高度", indexPath.row);
        NSLog(@"%@",  self.heightAry[indexPath.section][@(indexPath.row)]);
        return;
    }
}                                               

小结

大致也算是完成了知乎日报的内容,在学习的过程中出现很多问题,如对于MVC架构的一个职责不是很清楚,对于UITableVIew的函数调用的顺序不是很清楚,对于如何处理网络请求中异步回调的顺序问题,以及一些附加的功能还没有实现,比如说预加载和一个离线加载的内容,笔者会私下抽时间来实现这几个内容。

相关推荐
/**书香门第*/6 小时前
Laya ios接入goole广告,搭建环境 1
ios
wakangda12 小时前
React Native 集成 iOS 原生功能
react native·ios·cocoa
crasowas1 天前
iOS - 超好用的隐私清单修复脚本(持续更新)
ios·app store
ii_best1 天前
ios按键精灵脚本开发:ios悬浮窗命令
ios
Code&Ocean2 天前
iOS从Matter的设备认证证书中获取VID和PID
ios·matter·chip
/**书香门第*/2 天前
Laya ios接入goole广告,开始接入 2
ios
恋猫de小郭2 天前
什么?Flutter 可能会被 SwiftUI/ArkUI 化?全新的 Flutter Roadmap
flutter·ios·swiftui
网安墨雨2 天前
iOS应用网络安全之HTTPS
web安全·ios·https
福大大架构师每日一题3 天前
37.1 prometheus管理接口源码讲解
ios·iphone·prometheus
二流小码农3 天前
鸿蒙开发:简单了解属性动画
android·ios·harmonyos