9/54 Feb20-Feb26 iOS Swift GCD 并发 译文

这个拖延症真是害人,本来很早之前就该总结的,又拖到了今天。

代码下载地址

原文

最近在接手一个老项目的时候,原来的程序员是这样做的

图片 1效果图一.png图片 2效果图二.png图片 3效果图三.png

Grand Central Dispatch是一种用于管理并发操作的低级API。
GCD可以提高应用程序的响应能力,通过将计算成本高的任务放到后台。这是比锁和线程更容易的并发模型。

图片 4Paste_Image.png

这个实例主要是封装sqlite3数据库工具,并用这个工具实现记录、删除、修改、查询学生信息的功能,另外一个附属的功能就是根据学生的姓名首字母分组并添加索引。

在Swift
3中,GCD进行了重大改进,从基于C的API转移到包含新类和新数据结构的Swiftier
API。

但是这里的手势点击过程是背景变色还是图片变灰都达不到UIButton的原生点击效果,所以我就改完UIButton来实现。一般添加图片和文字的UIButton的按钮样式的这样的:

对于数据库,我做了两层封装。第一层是对数据库的基本操作进行抽象,第二层是对学生数据的操作进行抽象。这种分层的思想不仅能使处于底层的功能得到多次重用,调高效率;而且这样做逻辑清晰,易于定位问题,有益于维护与跟新。

第一部分将解释GCD的功能,并展示几个基本的GCD
functions。第二部分中,你将了解一些高级功能。

 [bidBtn setImage:[UIImage imageNamed:@"LPBid"] forState:UIControlStateNormal]; [bidBtn setTitle:@"招标公告" forState:UIControlStateNormal];

1、首先抽象出数据库基本操作工具类,而数据库的基本操作有:打开、关闭、建表、增、删、改、查……基于这些操作,我封装出如下五个方法来提供数据库的操作:

你将构建一个GooglyPuff App。
GooglyPuff是一个非优化的“线程不安全”的应用程序,使用Core
Image的面部检测API覆盖检测到的面部上的眼镜。您可以从照片库中选择要应用此效果的图像,或选择从互联网下载的图像。

图片 5Paste_Image.png

 * 打开数据库 * * @param path 数据库路径 * @param success 打开成功的回调 * @param falure 打开失败的回调 */+ openDBPath:(NSString *)path succesefulBlock:(sqlite3 *db))success andFailureBlock:(NSString *msg))failure{ sqlite3 *database = NULL; int result = sqlite3_open(path.UTF8String, &database); if (result == SQLITE_OK) { if  { success; } } else { if  { const char *msg = sqlite3_errmsg; failure([NSString stringWithUTF8String:msg]); } if  { [self closeDB:database succesefulBlock:nil andFailureBlock:nil]; } }}/** * 关闭数据库 * * @param database 数据库链接 * @param succese 成功的回调 * @param failure 失败的回调 */+ closeDB:(sqlite3 *)database succesefulBlock:succese andFailureBlock:(NSString *msg))failure{ int result = sqlite3_close; if (result == SQLITE_OK) { if  { succese(); } } else { if  { failure([NSString stringWithUTF8String:sqlite3_errmsg]); } }}/** * 执行SQL语句(不适应查询语句和blob二进制数据类型的操作) * * @param sqStr SQL语句 * @param database 数据库链接 * @param succese 成功的回调 * @param failure 失败的回调 */+ executeSql:(NSString *)sqStr toDatabase:(sqlite3 *)database succesefulBlock:succese andFailureBlock:(NSString *msg))failure{ DebugLog(@"%@", sqStr); char *msg = NULL; int result = sqlite3_exec(database, sqStr.UTF8String, NULL, NULL, &msg); if (result == SQLITE_OK) { if  { succese(); } } else { if  { failure([NSString stringWithUTF8String:msg]); } }}/** * 准备需要sqlite3_stmt结果集的SQL语句 * * @param sqStr SQL语句 * @param database 数据库连接 * @param succese 成功的回调 * @param failure 失败的回调 */+ prepareSql:(NSString *)sqStr fromDatabase:(sqlite3 *)database succesefulBlock:(sqlite3_stmt *stmt))succese andFailureBlock:(NSString *msg))failure{ DebugLog(@"%@", sqStr); sqlite3_stmt *stmt = NULL; int result = sqlite3_prepare_v2(database, sqStr.UTF8String, -1, &stmt, NULL); if (result == SQLITE_OK) { if  { succese; } } else { if  { failure(@"SQL语句是非法的。"); } }}

你在本教程中的任务是使用GCD优化应用程序,并确保你可以安全地从不同的线程调用代码。

达不到右边的效果,于是在网上开始寻找方法,很容易就找到这两个属性imageEdgeInsets和titleEdgeInsets,作用就是调整图片和文字在按钮里面的位置。二话不说开始调整…好像可以了,换个手机测试一下。明明在5s上达到右边的效果了,在7p上:

2、接着就是抽象学生数据功能类了。根据需要我抽象出了如下五个方法

下载初始项目,Run。

图片 6Paste_Image.png

/** * 获取所有学生 * * @param callBack 回调 */+ getAllStudents:(NSArray *students, NSString *msg))callBack;/** * 添加学生 * * @param studentModel 学生模型 * @param succese 添加成功回调 * @param failure 添加失败回调 */+ addStudent:(StudentModel *)studentModel succesefulBlock:(StudentModel *studentModel))succese andFailureBlock:(NSString *msg))failure;/** * 更新学生 * * @param studentModel 学生模型 * @param succese 更新成功回调 * @param failure 更新失败回调 */+ updateStudent:(StudentModel *)studentModel succesefulBlock:(StudentModel *studentModel))succese andFailureBlock:(NSString *msg))failure;/** * 按条件搜索学生 * * @param condition 条件 * @param callBack 搜索回调 */+ searchStudents:(NSString *)condition andCallBack:(NSArray *students, NSString *msg))callBack;/** * 删除学生 * * @param studentModel 学生模型 * @param succese 删除成功回调 * @param failure 删除失败回调 */+ deleteStudent:(StudentModel *)studentModel succesefulBlock:(StudentModel *studentModel))succese andFailureBlock:(NSString *msg))failure;

主屏幕初始为空。点击+,然后选择Le Internet下载预定义的图像。点击第一个图像,你会看到
googly eyes 添加到脸上。

调整的时候明明按照的比列在移动,但是在不同的屏幕上就是不一样。然后在找的过程中还发现了这个属性,contentHorizontalAlignment和contentVerticalAlignment,以前也看到过,以为是可以让内容垂直。但是用了一下,才发现,像原始的设置的图片和文字就是图2,默认的属性是这样的:

细节分析

图片 7

bidBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;bidBtn.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
  • 由于该功能类都是使用类方法,所以不能以实例变量来存储数据,因此声明全局变量static
    sqlite3
    *database来存储数据库的链接,并以static关键字修饰来避免其他源文件对其访问。
  • 类方法initialize是在手动调用累中任何方法前调用一次,所以在这个方法中打开数据库并创建学生表是非常合适的。

主要使用四个类:

而且这个时候,图片和文字是一个整体,一个整体,即你只调整一个edge属性,另外一个也会换位置,要想破除这个魔咒,只有设置

  • PhotoCollectionViewController:Initial view controller,
    显示缩略图。
  • PhotoDetailViewController:显示从PhotoCollectionViewController选择的照片,并添加眼球。
  • Photo:这是描述照片属性的 Protocol
    。它提供了一个图像,缩略图及其相应的状态。实现协议的两个类:DownloadPhoto,其从URL的实例实例化照片,以及
    AssetPhoto,实例化来自PHAsset的实例的照片。
  • PhotoManager:这管理所有的Photo对象。
bidBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;bidBtn.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
/** * 在手动调用类里的任何方法前自动调用一次 */+ initialize{ [SqliteDBAccess openDBPath:SqlitePathStr succesefulBlock:^(sqlite3 *db) { DebugLog(@"数据库打开成功!"); [SqliteDBAccess executeSql:[NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (identifier integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, studentNumber text NOT NULL UNIQUE, photo blob, age integer NOT NULL, address text, describe text);", StudentTableName] toDatabase:db succesefulBlock:^{ database = db; DebugLog(@"学生表创建成功!"); } andFailureBlock:^(NSString *msg) { DebugLog(@"学生表创建失败,%@", msg); }]; } andFailureBlock:^(NSString *msg) { DebugLog(@"数据库打开失败,%@", msg); }];}

这个App有几个问题。运行应用程序时,下载完成提醒太早了。你会在系列的第二部分解决这个问题。

图片 8Paste_Image.png

  • 在学生数据功能类的内部可以封装一个不公开的方法来从sqlite3_stmt结果集中获取学生模型对象

发表评论

电子邮件地址不会被公开。 必填项已用*标注