IOS框架:使用数据库类框架
2020-11-05 本文已影响0人
时光啊混蛋_97boy
目录
- 一、FMDB
- Demo
- 参考文献
一、FMDB
a、简介
FMDB
是用OC
语言封装了SQLite API
的数据库框架。
优点
- 使用时面向对象,避免了复杂的C语言代码
- 对比苹果自带的
Core Data
框架,更加轻量级和灵活 - 提供多线程安全处理数据库操作方法,保证多线程安全跟数据准确性
缺点
- 因为是OC语言开发,只能在iOS平台上使用,所以实现跨平台操作时存在限制性
-
FMDatabase
这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase
实例,会造成数据混乱等问题,为了保证线程安全,FMDB
提供方便快捷的FMDatabaseQueue
类
使用
- 在
FMDB
中,除查询以外的所有操作,都称为“更新”,create
、drop
、insert
、update
、delete
等都使用executeUpdate:
方法执行更新
b、FMDB的简单Demo
UserModel
@interface UserModel : NSObject
@property (nonatomic, strong) NSString *userId;
@property (nonatomic, strong) NSString *userName;
@property (nonatomic, strong) NSString *passWord;
@end
@implementation UserModel
@end
FMDBManager.h文件
@interface FMDBManager : NSObject
// 单例获取对象
+ (FMDBManager *)sharedFMDB;
// 创建表
- (void)createTable;
// 插入记录
- (void)insertUserWithUserName:(NSString *)userName password:(NSString *)password;
// 获取所有记录
- (NSMutableArray *)getAllUser;
// 删除某人所有信息
- (BOOL)deleteUser:(NSInteger)userID;
@end
FMDBManager.m文件
@interface FMDBManager()
{
NSString *_dataBasePath;// 数据库的路径
FMDatabase *_fmdbDataBase;// 数据库对象
BOOL _isFMDBopen;// 是否打开了数据库
}
@end
static FMDBManager *_sharedFMDB = nil;// 单例
@implementation FMDBManager
// 共享实例
+ (FMDBManager *)sharedFMDB
{
if (_sharedFMDB == nil)
{
_sharedFMDB = [[FMDBManager alloc] init];
}
return _sharedFMDB;
}
// 初始化
- (id)init
{
self = [super init];
if (self)
{
// 打开数据库
[self openDataBase];
}
return self;
}
@end
打开数据库
- (void)openDataBase
{
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dataBasePath = [documentPath stringByAppendingPathComponent:@"FMDBDemo.sqlite"];
_dataBasePath = dataBasePath;
// 创建数据库
if (_dataBasePath.length > 0)
{
_fmdbDataBase = [FMDatabase databaseWithPath:dataBasePath];
}
// 成功打开了数据库
if ([_fmdbDataBase open])
{
_isFMDBopen = YES;
}
else
{
_isFMDBopen = NO;
NSLog(@"打开数据库发生了错误");
}
}
判断数据库中是否存在某张表
- (BOOL)isExistTable:(NSString *)tableName
{
// 执行查询表的语句
FMResultSet *resultSet = [_fmdbDataBase executeQuery:@"select count(*) as 'count' from sqlite_master where type ='table' and name = ?", tableName];
while ([resultSet next])
{
// 表数
NSInteger count = [resultSet intForColumn:@"count"];
if (0 == count)
{
NSLog(@"表不存在");
return NO;
}
else
{
NSLog(@"表已存在");
return YES;
}
}
return NO;
}
创建表
- (void)createTable
{
NSString *createTableSQL = [NSString stringWithFormat:@"CREATE TABLE 'LuckCoffeeUser' ('userID' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'userName' text, 'passWord' text)"];
// 不存在瑞幸咖啡用户这张表格则进行创建
if (![self isExistTable:@"LuckCoffeeUser"])
{
BOOL isSuccess = [_fmdbDataBase executeUpdate:createTableSQL];
if (!isSuccess)
{
NSLog(@"当创建瑞幸咖啡用户表的时候发生了错误");
}
else
{
NSLog(@"成功创建了瑞幸咖啡用户表");
}
}
}
插入数据
- (void)insertUserWithUserName:(NSString *)userName password:(NSString *)password
{
NSString *insertUserSQL = [NSString stringWithFormat:@"insert into LuckCoffeeUser (userName, passWord) values(?, ?) "];
BOOL isSuccess = [_fmdbDataBase executeUpdate:insertUserSQL,userName,password];
if (!isSuccess)
{
NSLog(@"插入数据到瑞幸咖啡用户表的时候发生了错误");
}
else
{
NSLog(@"成功插入数据到瑞幸咖啡用户表");
}
}
获取所有记录
- (NSMutableArray *)getAllUser
{
NSMutableArray *userList = [[NSMutableArray alloc] init];
NSString *queryAllUserSQL = [NSString stringWithFormat:@"select * from LuckCoffeeUser"];
FMResultSet *resultSet = [_fmdbDataBase executeQuery:queryAllUserSQL];
while ([resultSet next])
{
UserModel *user = [[UserModel alloc] init];
user.userId = [NSString stringWithFormat:@"%d",[resultSet intForColumn:@"userID"]];
user.userName = [resultSet stringForColumn:@"userName"];
user.passWord = [resultSet stringForColumn:@"passWord"];
[userList addObject:user];
}
return userList;
}
删除某一条记录
- (BOOL)deleteUser:(NSInteger)userID
{
NSString *deleteUserSQL = [NSString stringWithFormat:@"delete from LuckCoffeeUser where userID=%ld",(long)userID];
return [_fmdbDataBase executeUpdate:deleteUserSQL];
}
使用方式
- (void)viewDidLoad
{
[super viewDidLoad];
[[FMDBManager sharedFMDB] createTable];// 创建表
// 插入
[[FMDBManager sharedFMDB] insertUserWithUserName:@"XieJiaPei" password:@"1525122040"];
[[FMDBManager sharedFMDB] insertUserWithUserName:@"BaiLuoMei" password:@"1625122040"];
[[FMDBManager sharedFMDB] insertUserWithUserName:@"FanYiCheng" password:@"1725122040"];
[[FMDBManager sharedFMDB] insertUserWithUserName:@"SunWuKong" password:@"1825122040"];
[[FMDBManager sharedFMDB] insertUserWithUserName:@"LinFengMian" password:@"1925122040"];
// 看看插入后的表格情况
NSArray *userListAfterInsert = [[FMDBManager sharedFMDB] getAllUser];
for (UserModel *user in userListAfterInsert)
{
NSLog(@"用户ID:%@,用户名称:%@,用户密码:%@",user.userId,user.userName,user.passWord);
}
[[FMDBManager sharedFMDB] deleteUser:2];
// 看看删除后的表格情况
NSArray *userListAfterDelete = [[FMDBManager sharedFMDB] getAllUser];
for (UserModel *user in userListAfterDelete)
{
NSLog(@"用户ID:%@,用户名称:%@,用户密码:%@",user.userId,user.userName,user.passWord);
}
}
输出结果
创建表格:
2020-10-20 18:17:41.461224+0800 框架Demo[28427:4977235] 表不存在
2020-10-20 18:17:41.462389+0800 框架Demo[28427:4977235] 成功创建了瑞幸咖啡用户表
插入数据:
2020-10-20 18:17:41.463243+0800 框架Demo[28427:4977235] 成功插入数据到瑞幸咖啡用户表
2020-10-20 18:17:41.463945+0800 框架Demo[28427:4977235] 成功插入数据到瑞幸咖啡用户表
2020-10-20 18:17:41.464546+0800 框架Demo[28427:4977235] 成功插入数据到瑞幸咖啡用户表
2020-10-20 18:17:41.465169+0800 框架Demo[28427:4977235] 成功插入数据到瑞幸咖啡用户表
2020-10-20 18:17:41.465786+0800 框架Demo[28427:4977235] 成功插入数据到瑞幸咖啡用户表
2020-10-20 18:17:41.465993+0800 框架Demo[28427:4977235] 用户ID:1,用户名称:XieJiaPei,用户密码:1525122040
2020-10-20 18:17:41.466070+0800 框架Demo[28427:4977235] 用户ID:2,用户名称:BaiLuoMei,用户密码:1625122040
2020-10-20 18:17:41.466127+0800 框架Demo[28427:4977235] 用户ID:3,用户名称:FanYiCheng,用户密码:1725122040
2020-10-20 18:17:41.466189+0800 框架Demo[28427:4977235] 用户ID:4,用户名称:SunWuKong,用户密码:1825122040
2020-10-20 18:17:41.466262+0800 框架Demo[28427:4977235] 用户ID:5,用户名称:LinFengMian,用户密码:1925122040
删除数据:
2020-10-20 18:17:41.467637+0800 框架Demo[28427:4977235] 用户ID:1,用户名称:XieJiaPei,用户密码:1525122040
2020-10-20 18:17:41.467712+0800 框架Demo[28427:4977235] 用户ID:3,用户名称:FanYiCheng,用户密码:1725122040
2020-10-20 18:17:41.467781+0800 框架Demo[28427:4977235] 用户ID:4,用户名称:SunWuKong,用户密码:1825122040
2020-10-20 18:17:41.467853+0800 框架Demo[28427:4977235] 用户ID:5,用户名称:LinFengMian,用户密码:1925122040
c、FMDB下载缓存图片的Demo
运行效果

CreateDatabase.h文件
/** 用来缓存网络图片的数据库 */
@interface CreateDatabase : NSObject
/** 创建表单 */
- (BOOL)createTable;
/** 查询数据 */
- (NSString *)selectData:(NSString *)remoteUrl;
/** 删除数据 */
- (BOOL)deleteData:(NSString *)remoteUrl;
/** 添加数据 */
- (BOOL)addData:(NSString *)imageUrl remoteUrl:(NSString *)remoteUrl;
@end
CreateDatabase.m文件
#import <FMDB.h>
@interface CreateDatabase ()
@property (nonatomic, strong, readwrite) FMDatabase *db;// 数据库
@property (nonatomic, strong, readwrite) FMDatabaseQueue *queue;// 任务队列
@end
@implementation CreateDatabase
.......
@end
初始化数据库
- (instancetype)init
{
self = [super init];
if (self)
{
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentPath stringByAppendingString:@"/xiejiapei.db"];
NSURL *url = [NSURL URLWithString:path];
NSLog(@"数据库地址为:%@", url);
// 创建数据库和任务队列
_queue = [FMDatabaseQueue databaseQueueWithURL:url];
_db = [FMDatabase databaseWithURL:url];
if (![_db open]) {
NSLog(@"打开数据库失败");
}
}
return self;
}
创建表单
- (BOOL)createTable
{
// 打开数据库
[_db open];
// 创建表单的SQL语句
NSString *sql = @"CREATE TABLE IF NOT EXISTS Image (remote_url text PRIMARY KEY NOT NULL, image_url text NOT NULL)";
// 执行SQL语句
BOOL success = [_db executeUpdate:sql];
if (!success || [_db hadError])// 创建表单失败
{
// 关闭数据库
[_db close];
return NO;
}
else
{
// 关闭数据库
[_db close];
return YES;
}
}
查询数据库
- (NSString *)selectData:(NSString *)remoteUrl
{
// 打开数据库
[_db open];
// 查询SQL语句
FMResultSet *userResult = [_db executeQuery:[NSString stringWithFormat:@"SELECT * FROM image where remote_url = '%@';", remoteUrl]];
// 获取查询结果
NSString *imageUrl = [[NSString alloc] init];
while ([userResult next])
{
imageUrl = [userResult stringForColumn:@"image_url"];
}
// 关闭数据库
[_db close];
return imageUrl;
}
删除数据
- (BOOL)deleteData:(NSString *)remoteUrl
{
// 打开数据库
[_db open];
// 删除数据的SQL语句
BOOL success = [_db executeUpdate:@"delete from image where image_url = ?", remoteUrl];
if (!success || [_db hadError])// 删除数据失败
{
// 关闭数据库
[_db close];
return NO;
}
else
{
// 关闭数据库
[_db close];
return YES;
}
}
添加数据
- (BOOL)addData:(NSString *)imageUrl remoteUrl:(NSString *)remoteUrl
{
// 打开数据库
[_db open];
// 添加数据的SQL语句
[_queue inDatabase:^(FMDatabase * _Nonnull db) {
[_db executeUpdate:@"INSERT INTO image ('image_url','remote_url') VALUES (?,?);", imageUrl ,remoteUrl];
}];
if ([_db hadError])// 添加数据失败
{
// 关闭数据库
[_db close];
return NO;
}
else
{
// 关闭数据库
[_db close];
return YES;
}
}
FMDBViewController.m文件
@interface FMDBViewController ()
// 获取得到的图片
@property (nonatomic,assign) UIImage *image;
// 图片缓存字典
@property (nonatomic, strong) NSMutableDictionary *imageCacheDict;
// 数据库
@property (nonatomic, strong) CreateDatabase *dataBase;
// 图像
@property (nonatomic, strong) UIImageView *imageView;
@end
@implementation FMDBViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self createSubviews];
}
- (void)createSubviews
{
self.view.backgroundColor = [UIColor whiteColor];
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(100, 100, 150, 150);
[self.view addSubview:imageView];
self.imageView = imageView;
self.imageCacheDict = [[NSMutableDictionary alloc] init];
self.dataBase = [[CreateDatabase alloc] init];
[self.dataBase createTable];
[self showImageWithURLString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1602901210&di=ce8b81d6dd50cf12263f36843f7bccd4&imgtype=jpg&er=1&src=http%3A%2F%2Fpics4.baidu.com%2Ffeed%2F3801213fb80e7bec1f568379f76a1e3e9a506b61.png%3Ftoken%3D84b2fa3895a800155fdf9802d26ca6c5"];
}
.......
@end
显示图片
- (void)showImageWithURLString:(NSString *)imageURL
{
// 根据imageURL查询数据库后将URL保存到图片缓存字典,imageURL作为key
self.imageCacheDict[imageURL] = [NSURL URLWithString:[self.dataBase selectData:[imageURL lastPathComponent]]];
// 获取刚才保存的URL
NSURL *cachedImageURL = self.imageCacheDict[imageURL];
// 有效期为一天,过期删除
NSArray *timeArray = [[cachedImageURL.path lastPathComponent] componentsSeparatedByString:@"+"];
NSTimeInterval time = [[NSDate date] timeIntervalSince1970] * 1000;
BOOL isValid = (time - [timeArray[1] integerValue]) < 24 *3600;
// 获取图片
UITableViewCell *cell;
if (cachedImageURL && isValid)// 缓存图片存在且有效
{
// 从URL中读取图片并显示
self.imageView.image = [self imageForURL:cachedImageURL];
}
else if (cachedImageURL && !isValid)// 缓存图片存在但是无效
{
// 从字典和数据库中移除缓存图片
[self.imageCacheDict removeObjectForKey:imageURL];
[self.dataBase deleteData:[imageURL lastPathComponent]];
// 下载新的图片并显示
[self downloadImage:imageURL forCell:cell];
}
else// 缓存图片不存在
{
// 下载新的图片并显示
[self downloadImage:imageURL forCell:cell];
}
}
// 从URL中读取图片
- (UIImage *)imageForURL:(NSURL *)imageURL
{
NSData *data = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:data];
return image;
}
下载(异步加载)
- (void)downloadImage:(NSString *)imageURL forCell:(UITableViewCell *)cell
{
// 下载远端图片数据
__weak FMDBViewController *weakself = self;
NSURL *downloadURL = [NSURL URLWithString:imageURL];
NSURLSession *URLSession = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [URLSession downloadTaskWithURL:downloadURL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 获取图片的URL
NSURL *cachedImageURL = [self writeImageToCacheFromLocation:location forDownloadURL:downloadURL];
// 在主线程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
// 保存到图片缓存字典
weakself.imageCacheDict[imageURL] = cachedImageURL;
// 保存到数据库
[weakself.dataBase addData:[NSString stringWithFormat:@"%@", cachedImageURL] remoteUrl:[NSString stringWithFormat:@"%@", [imageURL lastPathComponent]]];
// 更新UI
weakself.imageView.image = [self imageForURL:cachedImageURL];
});
}];
[task resume];
}
写入缓存
- (NSURL *)writeImageToCacheFromLocation:(NSURL *)location forDownloadURL:(NSURL *)downloadURL
{
// 创建缓存图片目录
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *applocationSupportURL = [[fileManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
NSString *imageDirPath = [applocationSupportURL.path stringByAppendingPathComponent:@"image"];
if (![fileManager fileExistsAtPath:imageDirPath])
{
[fileManager createDirectoryAtPath:imageDirPath withIntermediateDirectories:YES attributes:nil error:nil];
}
// 给路径传一个有效时间
NSTimeInterval time = [[NSDate date] timeIntervalSince1970] * 1000;
NSString *fileName = [downloadURL.path lastPathComponent];
NSString *imagePath = [imageDirPath stringByAppendingPathComponent:fileName];
NSString *imagePathWithTime = [imagePath stringByAppendingString:[NSString stringWithFormat:@"%@%f",@"+" , time]];
// 拷贝下载的图片到目标路径
NSURL *imageURL = [NSURL fileURLWithPath:imagePathWithTime];
[fileManager copyItemAtURL:location toURL:imageURL error:nil];
return imageURL;
}
Demo
Demo在我的Github上,欢迎下载。
UseFrameworkDemo