数据存储:FMDB-模型进行存取

镇楼图

写这个Blog的目的是为了记录的学习经历,代码写的不是很好,希望读者理解。
日常对数据库的操作,需要设计字段,感觉太繁琐了,想找个简化的方法,就想通过这样进行实现,这也就是一种思考方式。实际实现还是看需求。具体看代码:
1、导入FMDB

import FMDB

2、使用单利模式和必要属性

static let defaultManger = WDDataBaseManager()
typealias successBlock = () ->Void
typealias failBlock = () ->Void
private var tableName:String?

3、懒加载创建数据库(名称我随便取得)

lazy var fmdb:FMDatabase = {
        let path = NSHomeDirectory().appending("/Documents/testDB.db")
        let db = FMDatabase(path: path)
        return db
    }()

4、创建表

func creatTable(tableName:String) -> Void {
        fmdb.open()
        self.tableName = tableName
        let creatSql = "create table if not exists \(tableName) (id integer primary key autoincrement,model BLOB)"
        let result = fmdb.executeUpdate(creatSql, withArgumentsIn:[])
        if result{
            print("创建表成功")
        }
    }

5、删除表

 func dropTable() -> Void {
        let sql = "drop table if exists " + tableName!
        let result = fmdb.executeUpdate(sql, withArgumentsIn:[])
        if result{
            print("删除表成功")
        }
    }

6、插入数据

func insert(model:NSObject, successBlock: successBlock, failBlock: failBlock) -> Void {
        let modelData = try! NSKeyedArchiver.archivedData(withRootObject: model, requiringSecureCoding: false)
        let insertSql = "insert into " + tableName! + " (model) values(?)"
        do {
            try fmdb.executeUpdate(insertSql, values: [modelData])
            successBlock()
        } catch {
            print(fmdb.lastError())
            failBlock()
        }
    }

7、更新表

func update(model:NSObject,uid:Int32, successBlock: successBlock, failBlock: failBlock) -> Void {
        let modelData = try! NSKeyedArchiver.archivedData(withRootObject: model, requiringSecureCoding: false)
        let updateSql = "update " + tableName! + " set model = ? where id = ?"
        do {
            try fmdb.executeUpdate(updateSql, values: [modelData, uid])
            successBlock()
        } catch {
            print(fmdb.lastError())
            failBlock()
        }
    }

8、查询数据(这是查询所有数据,其他按需求设计)

func selectAll() -> [NSObject] {
        var tmpArr = [NSObject]()
        let selectSql = "select * from " + tableName!
        do {
            let rs = try fmdb.executeQuery(selectSql, values:nil)
            while rs.next() {
                var model = NSObject()
                let modelData  = rs.data(forColumn:"model")
                let id = rs.int(forColumn: "id")
                model = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(modelData!) as! NSObject
                model.wd_fmdb_id = id
                tmpArr.append(model)
            }
        } catch {
            print(fmdb.lastError())
        }
        return tmpArr
    }

9、删除数据(这是根据Id删除的)

func delete(uid:Int32, successBlock: successBlock, failBlock: failBlock) -> Void {
        let deleteSql = "delete from " + tableName! + " where id = ?"
        do {
            try fmdb.executeUpdate(deleteSql, values: [uid])
            successBlock()
        } catch {
            print(fmdb.lastError())
            failBlock()
        }
    }

10、新增分类添加默认Id

private var wd_id_key: String = "key"

extension NSObject {
    open var wd_fmdb_id:Int32? {
        get {
            return (objc_getAssociatedObject(self, &wd_id_key) as? Int32)
        } set(newValue) {
            objc_setAssociatedObject(self, &wd_id_key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
        }
    }
}

11、使用方法

//1. 在Appdelegate中打开数据库
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        DataBaseManager.defaultManger.creatTable()
        return true
 }
//2、添加数据
WDDataBaseManager.defaultManger.insert(model: model, successBlock: {
                print("成功")
            }, failBlock: {
                 print("失败")
            })
//3、修改数据
WDDataBaseManager.defaultManger.update(model: model, uid: self.model!.wd_fmdb_id!, successBlock: {
               print("成功")
            }, failBlock: {
                print("失败")
            })
//4、删除数据
WDDataBaseManager.defaultManger.delete(uid: model.wd_fmdb_id!, successBlock: {
                print("成功")
            }, failBlock: {
                print("失败")
            })
// 5、查询数据
WDDataBaseManager.defaultManger.selectAll()
  • 遵循NSCoding 重写三个方法
import UIKit

class Model: NSObject , NSCoding{

    public var name:String?
    public var phone:String?
    public var addres:String?
    
    override init() {
        super.init()
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(phone, forKey: "phone")
        aCoder.encode(addres, forKey: "addres")
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init()
        self.name = aDecoder.decodeObject(forKey: "name") as? String
        self.addres = aDecoder.decodeObject(forKey: "addres") as? String
        self.phone = aDecoder.decodeObject(forKey: "phone") as? String
    }
}

12、效果图

效果图

14、Demo地址:https://github.com/wudan-ios/FMDB-Model.git


补充Objective-C版本
1、接口文件

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (addId)

@property (nonatomic) NSInteger wd_fmdb_id;

@end

typedef void(^successBlock)(void);
typedef void(^failBlock)(void);

@interface WDDataBaseManager : NSObject

+ (instancetype)manager;
/** 创建表 */
- (void)createTableWithName:(NSString *)name;
/** 删除表 */
- (void)dropTable;
/** 添加数据 */
- (void)insertDataWithModel:(NSObject *)model successBlock:(successBlock)aSuccessBlock failBlock:(failBlock)aFailBlock;
/** 更新数据 */
- (void)updateDataWithModel:(NSObject *)model uid:(NSInteger)aUid successBlock:(successBlock)aSuccessBlock failBlock:(failBlock)aFailBlock;
/** 删除数据 */
- (void)deleteDataWithUid:(NSInteger)uid successBlock:(successBlock)aSuccessBlock failBlock:(failBlock)aFailBlock;
/** 查询全部数据 */
- (NSArray<NSObject *> *)queryAllData;

@end
NS_ASSUME_NONNULL_END

2、实现文件

#import "WDDataBaseManager.h"
#import <FMDB.h>
#import <objc/runtime.h>


static char *wd_id_key = "key";
@implementation NSObject (addId)

- (NSInteger)wd_fmdb_id {
    NSNumber *numberValue = objc_getAssociatedObject(self, wd_id_key);
    return numberValue.integerValue;
}

- (void)setWd_fmdb_id:(NSInteger)wd_fmdb_id {
    objc_setAssociatedObject(self, wd_id_key, @(wd_fmdb_id), OBJC_ASSOCIATION_ASSIGN);
}

@end

@interface WDDataBaseManager ()

@property (nonatomic, strong) FMDatabase *fmdb;
@property (nonatomic, copy) NSString *tableName;


@end

@implementation WDDataBaseManager

+ (instancetype)manager {
    static dispatch_once_t onceToken;
    static WDDataBaseManager *manager = nil;
    dispatch_once(&onceToken, ^{
        manager = [[WDDataBaseManager alloc] init];
    });
    return manager;
}

- (void)createTableWithName:(NSString *)name {
    [self.fmdb open];
    self.tableName = name;
    NSString *sql = [NSString stringWithFormat:@"create table if not exists %@ (id integer primary key autoincrement,model BLOB)", name];
    BOOL result = [self.fmdb executeUpdate:sql];
    if (result) {
        NSLog(@"表创建成功");
    }
}

- (void)dropTable {
    NSString *sql = [NSString stringWithFormat:@"drop table if exists %@", self.tableName];
    BOOL result = [self.fmdb executeUpdate:sql];
    if (result) {
        NSLog(@"表删除成功");
    }
}

- (void)insertDataWithModel:(NSObject *)model successBlock:(successBlock)aSuccessBlock failBlock:(failBlock)aFailBlock {
    NSData *modelData = [NSKeyedArchiver archivedDataWithRootObject:model];
    NSString *sql = [NSString stringWithFormat:@"insert into %@ (model) values(?)", self.tableName];
    BOOL result = [self.fmdb executeUpdate:sql withArgumentsInArray:@[modelData]];
    if (result) {
        aSuccessBlock();
    } else {
        aFailBlock();
    }
}

- (void)updateDataWithModel:(NSObject *)model uid:(NSInteger)aUid successBlock:(successBlock)aSuccessBlock failBlock:(failBlock)aFailBlock {
    NSData *modelData = [NSKeyedArchiver archivedDataWithRootObject:model];
    NSString *sql = [NSString stringWithFormat:@"update %@ set model = ? where id = ?", self.tableName];
    BOOL result = [self.fmdb executeUpdate:sql withArgumentsInArray:@[modelData, @(aUid)]];
    if (result) {
        aSuccessBlock();
    } else {
        aFailBlock();
    }
}

- (void)deleteDataWithUid:(NSInteger)uid successBlock:(successBlock)aSuccessBlock failBlock:(failBlock)aFailBlock {
    NSString *sql = [NSString stringWithFormat:@"delete from %@ where id = ?", self.tableName];
    BOOL result = [self.fmdb executeUpdate:sql withArgumentsInArray:@[@(uid)]];
    if (result) {
        aSuccessBlock();
    } else {
        aFailBlock();
    }
}

- (NSArray<NSObject *> *)queryAllData {
    NSMutableArray *array = [NSMutableArray array];
    NSString *sql = [NSString stringWithFormat:@"select * from %@",self.tableName];
    @try {
        FMResultSet *rs = [self.fmdb executeQuery:sql];
        while (rs.next) {
            NSObject *model = [[NSObject alloc] init];
            NSData *modelData = [rs dataForColumn:@"model"];
            int uid = [rs intForColumn:@"id"];
            
            model = [NSKeyedUnarchiver unarchiveObjectWithData:modelData];
            model.wd_fmdb_id = uid;
            [array addObject:model];
        }
    } @catch (NSException *exception) {
        NSLog(@"%@", self.fmdb.lastError);
    } @finally {
        NSLog(@"查询数据");
    }
    
   return array;
}

- (FMDatabase *)fmdb {
    if (!_fmdb) {
        NSString *path = [NSHomeDirectory() stringByAppendingString:@"/Documents/testDB.db"];
        _fmdb = [[FMDatabase alloc] initWithPath:path];
    }
    return _fmdb;
}

@end

3、使用方法

// 1、打开数据库,并创建表
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [[WDDataBaseManager manager] createTableWithName:@"test"];
    
    return YES;
}
// 2、添加数据
 [[WDDataBaseManager manager] insertDataWithModel:model successBlock:^{
        // TODO:
    } failBlock:^{
        // TODO:
    }];
// 3、查询数据
[[WDDataBaseManager manager] queryAllData]
// 4、修改数据
[[WDDataBaseManager manager] updateDataWithModel:model uid:self.model.wd_fmdb_id successBlock:^{
        // TODO:
    } failBlock:^{
         // TODO:
    }];
// 5、删除数据
[[WDDataBaseManager manager] deleteDataWithUid:model.wd_fmdb_id successBlock:^{
            // TODO:
        } failBlock:^{
            // TODO:
        }];
// 6、删除表
[[WDDataBaseManager manager] dropTable];
  • 插入表中的Model需要遵循<NSCoding>(实例代码)
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.phone forKey:@"phone"];
    [aCoder encodeObject:self.address forKey:@"address"];
}

- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
    if (self == [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"] ;
        self.phone = [aDecoder decodeObjectForKey:@"phone"];
        self.address = [aDecoder decodeObjectForKey:@"address"];
    }
    return self;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,922评论 2 89
  • Grit01阅读 211评论 0 1
  • 游戏时间:2018年6月3日 游戏职业:医生 游戏结果:没有出圈 这次游戏一开始也还是采用的只抽大买卖的方法。...
    zl216阅读 282评论 0 1
  • 项目在测试的时候发现在iOS11无法识别二维码 我的第一想到的解决方案是1.二维码太小了,二维码尺寸放大。2.是不...
    米诺dan阅读 2,221评论 1 1
  • 1.2日精进:敬畏—进入—体验—交给—持续 1,缺啥补啥,怕啥练啥; 2,一切为我所用,所用为团队家; 3,我想...
    京心达宁威阅读 159评论 0 0