美文网首页数据库
IOS框架:使用数据库类框架

IOS框架:使用数据库类框架

作者: 时光啊混蛋_97boy | 来源:发表于2020-11-05 09:56 被阅读0次

    目录

    • 一、FMDB
    • Demo
    • 参考文献

    一、FMDB

    a、简介

    FMDB是用OC语言封装了SQLite API的数据库框架。

    优点
    • 使用时面向对象,避免了复杂的C语言代码
    • 对比苹果自带的Core Data框架,更加轻量级和灵活
    • 提供多线程安全处理数据库操作方法,保证多线程安全跟数据准确性
    缺点
    • 因为是OC语言开发,只能在iOS平台上使用,所以实现跨平台操作时存在限制性
    • FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题,为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue
    使用
    • FMDB中,除查询以外的所有操作,都称为“更新”,createdropinsertupdatedelete等都使用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

    参考文献

    相关文章

      网友评论

        本文标题:IOS框架:使用数据库类框架

        本文链接:https://www.haomeiwen.com/subject/rkdovktx.html