【iOS】——知乎日报第五周总结

文章目录

  • 一、评论区展开与收缩
  • 二、FMDB库实现本地持久化
      • FMDB常用类:
      • FMDB的简单使用:
  • 三、点赞和收藏的持久化


一、评论区展开与收缩

有的评论没有被回复评论或者被回复评论过短,这时就不需要展开全文的按钮,所以首先计算被回复评论的文本高度,根据文本高度来决定是否隐藏展开全文的按钮。

CGSize constrainedSize = CGSizeMake(WIDTH - 70, CGFLOAT_MAX); // labelWidth为UILabel的宽度,高度设置为无限大NSDictionary *attributes = @{NSFontAttributeName: cell.replyLabel.font}; // label为要计算高度的UILabel控件CGRect textRect = [cell.replyLabel.text boundingRectWithSize:constrainedSizeoptions:NSStringDrawingUsesLineFragmentOriginattributes:attributescontext:nil];CGFloat textHeight = CGRectGetHeight(textRect);if (textHeight > 100) {cell.foldButton.hidden = NO;} else {cell.foldButton.hidden = YES;}

要实现评论区的展开全文和收起,需要先实现评论区文本的自适应高度,接着我用数组来记录每个按钮的状态,如果为展开状态则为1,如果为收起状态则为0。通过数组中按钮的状态为按钮的selected属性做出选择并改变cell的高度。当我点击按钮时就改变该按钮在数组中的相应值。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {if (indexPath.section == 0 && self.longComments != 0) {NSString* longStr = [self.discussModel.longCommentsArray[indexPath.row] content];NSString* longReplyStr = [self.discussModel.longCommentsArray[indexPath.row] reply_to][@"content"];CGSize constrainedSize = CGSizeMake(WIDTH - 70, CGFLOAT_MAX); // labelWidth为UILabel的宽度,高度设置为无限大UIFont *font = [UIFont systemFontOfSize:18.0];NSDictionary *attributes = @{NSFontAttributeName: font}; // label为要计算高度的UILabel控件CGRect textRect = [longStr boundingRectWithSize:constrainedSizeoptions:NSStringDrawingUsesLineFragmentOriginattributes:attributescontext:nil];CGFloat textHeight = CGRectGetHeight(textRect);CGSize constrainedSize02 = CGSizeMake(WIDTH - 70, CGFLOAT_MAX); // labelWidth为UILabel的宽度,高度设置为无限大UIFont *font02 = [UIFont systemFontOfSize:16.0];NSDictionary *attributes02 = @{NSFontAttributeName: font02}; // label为要计算高度的UILabel控件CGRect textRect02 = [longReplyStr boundingRectWithSize:constrainedSize02options:NSStringDrawingUsesLineFragmentOriginattributes:attributes02context:nil];CGFloat textHeight02 = CGRectGetHeight(textRect02);NSLog(@"长评论高度为:%f", textHeight);if ([self.discussModel.longButtonSelectArray[indexPath.row] isEqualToString:@"1"]) {return textHeight + textHeight02 + 180;}return textHeight + 180;} else {NSString* shortStr = [self.discussModel.shortCommentsArray[indexPath.row] content];NSString* shortReplyStr = [self.discussModel.shortCommentsArray[indexPath.row] reply_to][@"content"];CGSize constrainedSize = CGSizeMake(WIDTH - 70, CGFLOAT_MAX); // labelWidth为UILabel的宽度,高度设置为无限大UIFont *font = [UIFont systemFontOfSize:18.0];NSDictionary *attributes = @{NSFontAttributeName: font}; // label为要计算高度的UILabel控件CGRect textRect = [shortStr boundingRectWithSize:constrainedSizeoptions:NSStringDrawingUsesLineFragmentOriginattributes:attributescontext:nil];CGFloat textHeight = CGRectGetHeight(textRect);CGSize constrainedSize02 = CGSizeMake(WIDTH - 70, CGFLOAT_MAX); // labelWidth为UILabel的宽度,高度设置为无限大UIFont *font02 = [UIFont systemFontOfSize:16.0];NSDictionary *attributes02 = @{NSFontAttributeName: font02}; // label为要计算高度的UILabel控件CGRect textRect02 = [shortReplyStr boundingRectWithSize:constrainedSize02options:NSStringDrawingUsesLineFragmentOriginattributes:attributes02context:nil];CGFloat textHeight02 = CGRectGetHeight(textRect02);NSLog(@"段评论高度为:%f", textHeight);if ([self.discussModel.shortButtonSelectArray[indexPath.row] isEqualToString:@"1"]) {return textHeight + textHeight02 + 180;}return textHeight + 180;}  
}- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0 && self.longComments != 0) {if (indexPath.row == 0) {cell.commentsNumLabel.text = [NSString stringWithFormat:@"%ld条长评", self.longComments];}cell.foldButton.tag = indexPath.row * 2 + 1;if ([self.discussModel.longButtonSelectArray[indexPath.row] isEqualToString:@"1"]) {cell.foldButton.selected = YES;cell.replyLabel.numberOfLines = 0;} else {cell.foldButton.selected = NO;cell.replyLabel.numberOfLines = 2;}
}else {cell.foldButton.tag = indexPath.row * 2;if ([self.discussModel.shortButtonSelectArray[indexPath.row] isEqualToString:@"1"]) {cell.foldButton.selected = YES;cell.replyLabel.numberOfLines = 0;} else {cell.foldButton.selected = NO;cell.replyLabel.numberOfLines = 2;}
- (void)pressFold:(UIButton*)button {DiscussCustomCell* cell = (DiscussCustomCell*)[[button superview] superview];if ([self.discussModel.longButtonSelectArray[(button.tag - 1) / 2] isEqualToString:@"1"]) {[self.discussModel.longButtonSelectArray replaceObjectAtIndex:((button.tag - 1) / 2) withObject:@"0"];[self.discussView.tableview reloadData];} else {[self.discussModel.longButtonSelectArray replaceObjectAtIndex:((button.tag - 1) / 2) withObject:@"1"];[self.discussView.tableview reloadData];}if ([self.discussModel.shortButtonSelectArray[button.tag / 2] isEqualToString:@"1"]) {[self.discussModel.shortButtonSelectArray replaceObjectAtIndex:(button.tag / 2) withObject:@"0"];[self.discussView.tableview reloadData];} else {[self.discussModel.shortButtonSelectArray replaceObjectAtIndex:(button.tag / 2) withObject:@"1"];[self.discussView.tableview reloadData];}
}

请添加图片描述

请添加图片描述

二、FMDB库实现本地持久化

FMDB是iOS平台的SQLite数据库框架,以OC的方式封装了SQLite的C语言API。

FMDB常用类:

FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库用来执行SQL语句。
FMResultSet:使用FMDatabase执行查询后的结果集。
FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的。

FMDB的简单使用:

要使用FMDB库首先需要通过CocoaPods来安装这个第三方库

pod 'FMDB'

安装完成之后就可以进行使用了。

创建数据库

//获取数据库文件的路径NSString* doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];NSString *fileName = [doc stringByAppendingPathComponent:@"collectionData.sqlite"];//获得数据库self.collectionDatabase = [FMDatabase databaseWithPath:fileName];//打开数据库if ([self.collectionDatabase open]) {BOOL result = [self.collectionDatabase executeUpdate:@"CREATE TABLE IF NOT EXISTS collectionData (mainLabel text NOT NULL, nameLabel text NOT NULL, imageURL text NOT NULL, networkURL text NOT NULL, dateLabel text NOT NULL, nowLocation text NOT NULL, goodState text NOT NULL, collectionState text NOT NULL, id text NOT NULL);"];if (result) {NSLog(@"创表成功");} else {NSLog(@"创表失败");}}

数据库增加数据

//插入数据
- (void)insertData {if ([self.collectionDatabase open]) {NSString *string = @"GenShen";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, @"114514",@"GenShen"];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, @"爱玩原神"];if (!result) {NSLog(@"数据删除失败");} else {NSLog(@"数据删除成功");}[self.collectionDatabase close];}
}

数据库查询数据

//查询数据
- (void)queryData {if ([self.collectionDatabase open]) {FMResultSet* resultSet = [self.collectionDatabase executeQuery:@"SELECT * FROM collectionData"];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];}
}

三、点赞和收藏的持久化

要实现点赞和收藏的持久化就需要用到前面所提到的FMDB库进行操作。在需要用到数据库的部分进行数据库的创建和一些基本操作例如增删改查。以收藏持久化为例子,当点击点赞收藏按钮的时候,进入到数据库查询函数进行查询,如果找到就将该数据进行删除然后将按钮状态设置为未选中状态。如果没有找到该数据就进行添加然后将按钮状态设置为选中状态

- (void)pressCollect:(UIButton*)button {NSString* collectionIdStr = [NSString stringWithFormat:@"%ld", self.idStr];int flag = [self queryCollectionData];if (flag == 1) {self.mainWebView.collectButton.selected = NO;[self deleteCollectionData:collectionIdStr];} else {self.mainWebView.collectButton.selected = YES;[self insertCollectionData:self.mainLabel andUrl:self.imageUrl andStr:collectionIdStr];}
}

当滑动切换页面请求新闻额外信息时也需要先进行判断当前点赞和收藏的按钮状态

[[ExtraManager sharedSingleton] ExtraGetWithData:^(GetExtraModel * _Nullable extraModel) {dispatch_async(dispatch_get_main_queue(), ^{int flag = [self queryLikesData];int collectFlag = [self queryCollectionData];self.mainWebView.discussLabel.text = [NSString stringWithFormat:@"%ld", extraModel.comments];self.mainWebView.likeLabel.text = [NSString stringWithFormat:@"%ld", extraModel.popularity];self.longComments = extraModel.long_comments;self.shortComments = extraModel.short_comments;if (flag == 1) {self.mainWebView.likeButton.selected = YES;NSInteger likesNum = [self.mainWebView.likeLabel.text integerValue];likesNum++;self.mainWebView.likeLabel.text = [NSString stringWithFormat:@"%ld", likesNum];NSString* likesIdStr = [NSString stringWithFormat:@"%ld", self.idStr];[self insertLikesData:likesIdStr];} else {self.mainWebView.likeButton.selected = NO;}if (collectFlag == 1) {self.mainWebView.collectButton.selected = YES;} else {self.mainWebView.collectButton.selected = NO;}NSLog(@"额外信息获取成功");});} andError:^(NSError * _Nullable error) {NSLog(@"额外信息获取失败");} andIdStr:self.idStr];

收藏数据库部分代码如下:

//创建
- (void)databaseInit {NSString* likesDoc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];NSLog(@"%@", likesDoc);NSString * likesFileName = [likesDoc stringByAppendingPathComponent:@"likesData.sqlite"];self.likesDatabase = [FMDatabase databaseWithPath:likesFileName];if ([self.likesDatabase open]) {BOOL result = [self.likesDatabase executeUpdate:@"CREATE TABLE IF NOT EXISTS likesData (id text NOT NULL);"];if (result) {NSLog(@"创表成功");} else {NSLog(@"创表失败");}}NSString* collectionDoc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];NSLog(@"%@", collectionDoc);NSString * collectionFileName = [collectionDoc stringByAppendingPathComponent:@"collectionData02.sqlite"];self.collectionDatabase = [FMDatabase databaseWithPath:collectionFileName];if ([self.collectionDatabase open]) {BOOL result  = [self.collectionDatabase executeUpdate:@"CREATE TABLE IF NOT EXISTS collectionData (mainLabel text NOT NULL, imageURL text NOT NULL, id text NOT NULL);"];if (result) {NSLog(@"创表成功");} else {NSLog(@"创表失败");}}}
//增加
- (void)insertCollectionData:(NSString *)mainLabel andUrl:(NSString *)imageURL andStr:(NSString*)string {if ([self.collectionDatabase open]) {BOOL result = [self.collectionDatabase executeUpdate:@"INSERT INTO collectionData (mainLabel, imageURL, id) VALUES (?, ?, ?);", mainLabel, imageURL,string];if (!result) {NSLog(@"增加收藏数据失败");}else{NSLog(@"增加收藏数据成功");}}[self.collectionDatabase close];
}
//删除
- (void)deleteCollectionData:(NSString*)string {if ([self.collectionDatabase open]) {NSString *sql = @"delete from collectionData WHERE id = ?";BOOL result = [self.collectionDatabase executeUpdate:sql, string];if (!result) {NSLog(@"删除收藏数据失败");}else{NSLog(@"删除收藏数据成功");}}[self.collectionDatabase close];
}//查询
- (int)queryCollectionData {if ([self.collectionDatabase open]) {FMResultSet* collectionResultSet = [self.collectionDatabase executeQuery:@"SELECT * FROM collectionData"];int count = 0;while ([collectionResultSet next]) {NSString *sqlIdStr = [NSString stringWithFormat:@"%@", [collectionResultSet objectForColumn:@"id"]];NSInteger sqlId = [sqlIdStr integerValue];NSLog(@"第 %d 个收藏数据库数据:%ld", count++ ,sqlId);if (self.idStr == sqlId) {[self.collectionDatabase close];return 1;}}}[self.collectionDatabase close];return 0;
}

请添加图片描述

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/198034.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

量化交易:借助talib使用技术分析指标

什么是技术分析? 所谓股票的技术分析,是相对于基本面分析而言的。基本分析法着重于对一般经济情况以及各个公司的经营管理状况、行业动态等因素进行分析,以此来研究股票的价值,衡量股价的高低。而技术分析则是透过图表或技术指标…

vulhub redis-4-unacc

环境搭建 cd vulhub/redis/4-unacc docker-compose up -d 漏洞复现 检测 redis-cli -h ip 使用redis工具 工具地址:https://github.com/vulhub/redis-rogue-getshell 下载完成后,先进入RedisModulesSDK/exp/ 目录进行make操作 获得exp.so后可以进行…

Jenkinsfile+Dockerfile前端vue自动化部署

前言 本篇主要介绍如何自动化部署前端vue项目 其中,有两种方案: 第一种是利用nginx进行静态资源转发;第二种方案是利用nodejs进行启动访问; 各个组件版本如下: Docker 最新版本;Jenkins 2.387.3nginx …

物联网AI MicroPython学习之语法 I2C总线

学物联网,来万物简单IoT物联网!! I2C 介绍 模块功能: I2C Master设备驱动 接口说明 I2C - 构建硬件I2C对象 函数原型:I2C(id, scl, sda, freq)参数说明: 参数类型必选参数?说明idintYI2C外设&#xff…

带你快速掌握Linux最常用的命令(图文详解)- 最新版(面试笔试常考)

最常用的Linux指令(图文详解)- 最新版 ls:列出目录中的文件和子目录(重点)cd:改变当前工作目录绝对路径:相对路径 pwd:显示当前工作目录的路径mkdir:创建一个新的目录tou…

【开源】基于Vue.js的音乐偏好度推荐系统的设计和实现

项目编号: S 012 ,文末获取源码。 \color{red}{项目编号:S012,文末获取源码。} 项目编号:S012,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1…

spring中的DI

【知识要点】 控制反转(IOC)将对象的创建权限交给第三方模块完成,第三方模块需要将创建好的对象,以某种合适的方式交给引用对象去使用,这个过程称为依赖注入(DI)。如:A对象如果需要…

代码随想录算法训练营Day 54 || 392.判断子序列、115.不同的子序列

392.判断子序列 力扣题目链接(opens new window) 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,&quo…

多svn仓库一键更新脚本分享

之前分享过多git仓库一键更新脚本,本期就分享下svn仓库的一键更新脚本 1、首先需要设置svn为可执行命令行 打开SVN安装程序,选择modify,然后点击 command client tools,安装命令行工具 2、update脚本 echo 开始更新SVN目录&…

计算机视觉:使用opencv实现车牌识别

1 引言 汽车车牌识别(License Plate Recognition)是一个日常生活中的普遍应用,特别是在智能交通系统中,汽车牌照识别发挥了巨大的作用。汽车牌照的自动识别技术是把处理图像的方法与计算机的软件技术相连接在一起,以准…

Linux管道的工作过程

常用的匿名管道(Anonymous Pipes),也即将多个命令串起来的竖线。管道的创建,需要通过下面这个系统调用。 int pipe(int fd[2]) 我们创建了一个管道 pipe,返回了两个文件描述符,这表示管道的两端&#xff…

jvm 内存结构 ^_^

1. 程序计数器 2. 虚拟机栈 3. 本地方法栈 4. 堆 5. 方法区 程序计数器 定义: Program Counter Register 程序计数器(寄存器) 作用,是记住下一条jvm指令的执行地址 特点: 是线程私有的 不会存在内存溢出 虚拟机栈…

SQL练习02

1.买下所有产品的客户 SQL Create table If Not Exists Customer (customer_id int, product_key int); Create table Product (product_key int); Truncate table Customer; insert into Customer (customer_id, product_key) values (1, 5); insert into Customer (customer_…

开源供应链管理系统 S2B2B2C系统方案及源码输出

这个开源供应链管理系统提供针对企业供应链管理需求的开放源代码解决方案。通过开源供应链管理系统,企业能够实现对供应商、进销存和物流配送等方面的全面管理和优化,涵盖了从供应商选择到门店到消费者服务交付的整个流程。开源系统使企业能够根据自身需…

Linux|僵死进程

1.僵死进程产生的原因或者条件: 什么是僵死进程? 当子进程先于父进程结束,父进程没有获取子进程的退出码,此时子进程变成僵死进程. 简而言之,就是子进程先结束,并且父进程没有获取它的退出码; 那么僵死进程产生的原因或者条件就是:子进程先于父进程结束,并且父进程没有获取…

使用内网穿透解决支付宝回调地址在公网问题

使用natapp解决内网穿透问题 前言NATAPP使用购买隧道 支付宝回调地址测试之后的学习计划 前言 最近一个项目用到了支付宝,但是本地调试的时候发现支付宝的回调地址需要在公网上能够访问到。为了更加方便地调试,就使用了natapp内网穿透,将回调…

mount /dev/mapper/centos-root on sysroot failed处理

今天发现centos7重启开不进去系统 通过查看日志主要告警如下 修复挂载目录 xfs_repair /dev/mapper/centos-root不行加-L参数 xfs_repair -L /dev/mapper/centos-root重启 reboot

C++各种字符转换

C各种字符转换 一.如何将char数组转化为string类型二. string转char数组:参考 一.如何将char数组转化为string类型 在C中,可以使用string的构造函数或者赋值操作符来将char数组转换为string类型。 方法1:使用string的构造函数 const char* c…

面向对象与面向过程的区别

面向对象 以对象为中心,把数据封装成为一个整体,其他数据无法直接修改它的数据,将问题分解成不同对象,然后给予对象相应的属性和行为。 面向过程 关注代码过程,直接一程序来处理数据,各模块之间有调用与…

js添加dom到指定div之后,并给添加的dom类名,然后设置其样式,以及el-popover层级z-index过高问题解决。

遇到一个需求,Vue项目做一个表格,要求表头与表格内容分开,如下效果所示,表头与表格有个高度间隔边距(箭头所示),因为默认我们的el-table的表头与内容是一起的: 思路:通过querySelector获取el-table__header-wrapper元素,通过createElement创建一个div,通过 newElem…