[iOS]知乎日报第四周总结-唐妞不等式秒了之没写完不等于不能发博客
文章目录
小结
本周依旧很摆
但这不耽误我写博客
还差一些部分这个知乎日报就结束了
被自适应高度cell为难了好久
自适应高度cell
法一:写个方法计算label高度
-(CGSize)ZFYtextHeightFromTextString:(NSString *)text width:(CGFloat)textWidth fontSize:(CGFloat)size{
//计算 label需要的宽度和高度
NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:size]};
CGRect rect = [text boundingRectWithSize:CGSizeMake(textWidth, MAXFLOAT) options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
CGSize size1 = [text sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:size]}];
return CGSizeMake(size1.width, rect.size.height);
}
法二:通过Masonry布局实现
通过masonry的约束来撑开cell的高度是很简单实用的方法
这里就不做背景介绍了
简单讲下步骤
然后是需要注意的一些点
步骤
要使用 Masonry 实现自适应高度,你可以借助 UITableView 的 estimatedRowHeight 和 rowHeight 属性,以及 Masonry 的自动布局功能。以下是实现步骤:
-
首先,确保你的 UITableViewCell 中的子视图使用了 Masonry 进行自动布局。
-
在 UITableView 的数据源方法中,设置 estimatedRowHeight 和 rowHeight 属性。estimatedRowHeight 用于估算行高,rowHeight 用于设置具体的行高。
tableView.estimatedRowHeight = 100; // 估算的行高
tableView.rowHeight = UITableViewAutomaticDimension; // 设置为自动计算高度
- 在 UITableViewCell 的 - (void)awakeFromNib 方法中,添加子视图并设置 Masonry 约束。
- (void)awakeFromNib {
[super awakeFromNib];
// 添加子视图并设置Masonry约束
[self.contentView addSubview:self.titleLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView.mas_top).offset(8);
make.left.equalTo(self.contentView.mas_left).offset(8);
make.right.equalTo(self.contentView.mas_right).offset(-8);
}];
// 添加其他子视图并设置Masonry约束
}
通过上述步骤,你就可以使用 Masonry 实现自适应高度。当内容发生变化时,UITableView 会根据实际内容重新计算高度,从而实现动态高度的 UITableViewCell。
注意
- 使用masonry约束后 不要再使用下面的方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- 将masonry布局放在以下方法中,才能在调用时正确撑开cell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;
- 想要撑开cell必须保证你的布局内包括对contentView的top与bottm都要有所约束
[self.imagebtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).offset(20);
make.top.equalTo(self.contentView).offset(10);
make.size.mas_equalTo(30);
}];
[self.namelabel mas_makeConstraints:^(MASConstraintMaker *make) {
//由于要自适应的cell,所以不用宽高约束
make.left.mas_equalTo(self.imagebtn.mas_right).mas_offset(10);
make.top.equalTo(self.imagebtn.mas_top).offset(-5);
make.width.mas_offset(300);
}];
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.imagebtn.mas_right).mas_offset(10);
make.top.equalTo(self.namelabel.mas_bottom).offset(5);
make.right.mas_equalTo(-20);
make.width.mas_offset(300);
make.height.mas_lessThanOrEqualTo(self.contentView.bounds.size.height);
}];
[self.sublabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.imagebtn.mas_right).mas_offset(10);
make.top.equalTo(self.label.mas_bottom).offset(5);
make.width.mas_offset(300);
}];
[self.timelabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.imagebtn.mas_right).mas_offset(10);
make.top.equalTo(self.sublabel.mas_bottom).offset(10);
make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);
make.width.mas_offset(300);
}];
[self.commentbtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.sublabel.mas_bottom).offset(5);
make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);
make.right.mas_equalTo(-20);
make.size.mas_equalTo(20);
}];
[self.likebtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.sublabel.mas_bottom).offset(5);
make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);
make.right.mas_equalTo(self.commentbtn.mas_left).mas_offset(-30);
make.size.mas_equalTo(20);
}];
可折叠cell
这个要多讲吗
主要不是使用 是复用的问题啦
但是咱们还是过一遍叭
使用
除去和普通tableView的超初始化以外 还有一点要准备
foldtableView.userInteractionEnabled = YES;
当然 展开以后肯定也需要重新设置大小
_foldtableView.frame = CGRectMake(210, 140, 140, 30 * _foldarrayData.count);
然后还有这个也是必须的 让我们能展开这个cell
cell.userInteractionEnabled = YES;
复用
tableView的复用机制:注册的一类cell中若有多个cell,那么在后续刷新的时候后面的cell会利用上面的cell的视图及其数据,若两个cell中需要显示的视图不完全一样,那么就会出现下方的cell刷新出本来不需要的视图
解决方法也简单:
//例如:
if (cell == nil) {
cell = [[CommentTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"14"];
} else {
//删除cell的所有子视图
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
//重新初始化,将需要的UI控件重新添加到视图上,但没有之前cell的数据
cell = [[CommentTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"14"];
}
FMDB
好的 让我们来看看FMDB
这个也需要通过pod安装 这里也不赘述了
看看使用意义
意义
- FMDB是iOS平台的SQLite数据库框架
- FMDB以OC的方式封装了SQLite的C语言API
- 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
- 对比苹果自带的Core Data框架,更加轻量级和灵活
- 提供了多线程安全的数据库操作方法,有效地防止数据混乱
核心
FMDB有三个主要的类
FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库用来执行SQL语句
FMResultSet:使用FMDatabase执行查询后的结果集
FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的
步骤
这里有篇很详细的
还是过一遍
顺便水一点字数
获取路径
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"%@", doc);
NSString *fileName = [doc stringByAppendingPathComponent:@"collectionData.sqlite"];
获取打开
FMDatabase *collectionDatabase = [FMDatabase databaseWithPath:fileName];
BOOL executeUpdate = [dataBase executeUpdate:@"CREATE TABLE IF NOT EXISTS t_collect (id text NOT NULL);"];
if (executeUpdate) {
NSLog(@"创建表成功");
} else {
NSLog(@"创建表失败");
}
通常对数据库的操作,我们一般称为CURD,即对表进行创建(Create)、更新(Update)、读取(Read)和删除(Delete)操作。
插入数据
//插入数据
- (void)insertData {
if ([self.collectionDatabase open]) {
NSString *string = @"hi world";
BOOL result = [self.collectionDatabase executeUpdate:@"INSERT INTO collectionData (mainLabel, nameLabel, imageURL, networkURL, dateLabel, nowLocation, goodState, collectionState, id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);", string, string, string, string, string, string, string, string, string];
if (!result) {
NSLog(@"增加数据失败");
}else{
NSLog(@"增加数据成功");
}
[self.collectionDatabase close];
}
}
更新数据
// 更新数据
- (void)updateData {
if ([self.collectionDatabase open]) {
NSString *sql = @"UPDATE collectionData SET id = ? WHERE nameLabel = ?";
BOOL result = [self.collectionDatabase executeUpdate:sql, @"1", @"hi world"];
if (!result) {
NSLog(@"数据修改失败");
} else {
NSLog(@"数据修改成功");
}
[self.collectionDatabase close];
}
}
删除数据
// 删除数据
- (void)deleteData {
if ([self.collectionDatabase open]) {
NSString *sql = @"delete from collectionData WHERE collectionState = ?";
BOOL result = [self.collectionDatabase executeUpdate:sql, @"xixixixi"];
if (!result) {
NSLog(@"数据删除失败");
} else {
NSLog(@"数据删除成功");
}
[self.collectionDatabase close];
}
}
查找数据
// 查询数据
- (void)queryData {
if ([self.collectionDatabase open]) {
// 1.执行查询语句
FMResultSet *resultSet = [self.collectionDatabase executeQuery:@"SELECT * FROM collectionData"];
// 2.遍历结果
while ([resultSet next]) {
NSString *mainLabel = [resultSet stringForColumn:@"mainLabel"];
NSLog(@"mainLabel = %@",mainLabel);
NSString *nameLabel = [resultSet stringForColumn:@"nameLabel"];
NSLog(@"nameLabel = %@",nameLabel);
NSString *imageURL = [resultSet stringForColumn:@"imageURL"];
NSLog(@"imageURL = %@",imageURL);
NSString *networkURL = [resultSet stringForColumn:@"networkURL"];
NSLog(@"networkURL = %@",networkURL);
NSString *dateLabel = [resultSet stringForColumn:@"dateLabel"];
NSLog(@"dateLabel = %@",dateLabel);
NSString *nowLocation = [resultSet stringForColumn:@"nowLocation"];
NSLog(@"nowLocation = %@",nowLocation);
NSString *goodState = [resultSet stringForColumn:@"goodState"];
NSLog(@"goodState = %@",goodState);
NSString *collectionState = [resultSet stringForColumn:@"collectionState"];
NSLog(@"collectionState = %@",collectionState);
NSString *id = [resultSet stringForColumn:@"id"];
NSLog(@"id = %@",id);
}
[self.collectionDatabase close];
}
}
好了新手教程就到这里了
加油吧勇士!