美文网首页
FMDB 使用方法【转】

FMDB 使用方法【转】

作者: 小船_d15e | 来源:发表于2020-12-24 16:54 被阅读0次

    (一)Realm简单介绍
    1.什么是Realm
    Realm 是由美国YCombinator孵化的创业团队历时几年打造的第一款针对移动设备设计的数据库。是一个跨平台的移动数据库引擎,目前支持iOS、Android平台,同时支持Objective-C、Swift、Java、React Native、Xamarin等多种编程语言。Realm并不是对SQLite或者CoreData的简单封装, 是由核心数据引擎C++打造,是拥有独立的数据库存储引擎,可以方便、高效的完成数据库的各种操作
    2.Realm的特性
    a.移动设备支持:Realm是第一个针对手机平板和可穿戴设备涉及的数据库,基本全平台支持。
    b.简单:Realm的安装和借入简易,不同于Core Data,不需要开发者配置模型层结构,从开始接触到上手使用,只需要短短几分钟而已。
    c.现代:关系型数据库,支持泛型。
    d.快速:官方称比SQLite常规操作要快。
    e.跨平台:同时支持多个平台,节省资源。
    3.Realm的资源
    官方文档:https://realm.io (学习的首选参考手册)
    GitHub:https://github.com/realm/realm-cocoa
    可视化工具: Realm Browser

    image

    如果需要调试, 可以通过NSHomeDirectory()打印出Realm数据库地址, 找到对应的Realm文件, 然后用Realm Browser可视化工具打开即可
    Xcode 插件有助于创建Realm数据模型

    image

    (二)Realm的安装
    (1)手动安装
    a.* 要使用 Realm 数据库, 首先要导入 Realm.framework 这个框架, 从Realm官网上可以下载,我使用的是realm-objc-3.14.1 这个版本, 下载解压完成后, 将iOS文件夹中的 static文件中的静态库拖到工程中

    image

    b.然后点击 Targets, 选择工程, 点击 Build Phases, 添加libz.tbd 和 libc++.tbd 两个库

    image

    c.点击 plugin 文件中的项目, 运行,然后退出 XCode, 重启 XCode, 就可以安装成功插件, 我们就可以利用插件自动生成模型类

    image

    d.安装成功插件后, command + N 在新建文件的时候滑到最底端就可以看见Realm Model Object, 它就是Realm 数据库存储的模型对象, 你要存储的数据都是继承自这个类的. 所以我们新建 Realm Model Object 文件时, 就会自动帮我们建立一个.h 和.m 文件,就跟创建继承NSObject类是一样的

    image

    e.在用到的文件中引入#import <Realm/Realm.h> 即可使用
    ⚠️:官方文档介绍了四种安装说明,我只整理了一种最简单快速的方法
    (2)工程中使用
    (三)Realm定义的类
    Realm框架中,定义了二十个核心类、常量、枚举类型、协议等,常用的如:RLMRealm类、RLMObject类、RLMResults类等, 我们可以从Realm官方网站上查看所有的定义以及使用说明
    1.Realm类
    一个Realm类的对象可以认为是一个Realm数据库,Realm数据库既可以存储到硬盘上,也可以存储到内存中。Realm类是框架的核心类,如同FMDB中的FMDatabase ,Core Data管理对象的上下文managed object context一样

    //获取默认的Realm数据库
    + (instancetype)defaultRealm;
    //实例化一个realm数据库,根据配置参数获取对应的Realm数据库
    + (nullable instancetype)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error;
    //根据指定的文件URL初始化一个Realm数据库
    + (instancetype)realmWithURL:(NSURL *)fileURL;
    //对Realm 数据库进行读写操作之前,只能开启一个写事务
    - (void)beginWriteTransaction;
    //对Realm数据库进行读写操作完成之后,关闭对应的写事务
    - (void)commitWriteTransaction NS_SWIFT_UNAVAILABLE("");
    //没有足够的磁盘空间来保存写入或由于意外的I / O错误,此方法可能会失败, 并返回error信息
    - (BOOL)commitWriteTransaction:(NSError **)error;
    //在当前写入事务中提交所有写入操作,而不收到此写入事件的特定通知
    - (BOOL)commitWriteTransactionWithoutNotifying:(NSArray<RLMNotificationToken *> *)tokens error:(NSError **)error;
    //回滚在当前写入事务期间进行的所有写入并结束事务
    - (void)cancelWriteTransaction;
    //执行写入事务块内特定的操作
    - (void)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block NS_SWIFT_UNAVAILABLE("");
    - (BOOL)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block error:(NSError **)error;
    //添加或更新一个对象
    - (void)addObject:(RLMObject *)object;
    //将现有对象添加或更新到Realm中, 有则更新没有则插入
    - (void)addOrUpdateObject:(RLMObject *)object;
    //添加或更新多个对象
    - (void)addObjects:(id<NSFastEnumeration>)objects;
    - (void)addOrUpdateObjects:(id<NSFastEnumeration>)objects;
    //删除对象
    - (void)deleteObject:(RLMObject *)object;
    - (void)deleteObjects:(id)array;
    - (void)deleteAllObjects;
    
    
    1. RLMObject类
      在Realm数据库中存储的都是RMObject对象,RLMObject类是所有可以存储在Realm数据库中的对象的根类。
      在RLMObject类中,我们可以添加属性,添加的属性类型可以支持如下类型:
      NSString:字符串
      NSInteger, int, long, float, double:数字型,注意没有CGFloat
      BOOL/bool:布尔型
      NSDate:日期型
      NSData:二进制字符型
      NSNumber<X>: 其中X必须RLMInt, RLMFloat, RLMDouble或 RLMBool类型
      RLMArray<X>: 其中X必须是RLMObject类的子类, 用于建模多对多关系
      RLMObject的子类,用于建模多对一关系
    //创建RLMObject对象, 传入一个NSArray或NSDictionary实例来设置对象属性的值
    - (instancetype)initWithValue:(id)value NS_DESIGNATED_INITIALIZER;
    //获取RLMObject对象的类名
    + (NSString *)className;
    //在Realm数据库中,获取该RLMObject类的所有对象
    + (RLMResults *)allObjects;
    
    //根据查询条件返回满足条件的所有RLMObject类的对象
    + (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...;
    
    //使用默认Realm中的给定主键检索此对象类型的单个实例
    + (nullable instancetype)objectForPrimaryKey:(nullable id)primaryKey;
    
    //从指定的Realm返回此对象类型的所有对象
    + (nonnull RLMResults *)allObjectsInRealm:(nonnull RLMRealm *)realm;
    
    //返回与指定Realm中给定谓词匹配的此对象类型的所有对象
    + (nonnull RLMResults *)objectsInRealm:(nonnull RLMRealm *)realm where:(nonnull NSString *)predicateFormat, ...;
    
    
    1. RLMResults类
      当我们执行一个查询操作后,查询出满足条件的RLMObject对象会存放在一个RLMResults对象中,RLMResults类是一个数组类型的数据结构,因此在其类定义中,提供了很多与数组类似的属性和方法。
    //结果集合中的对象个数
    @property (readonly, assign, nonatomic) NSUInteger count;
    //结果集合中对象的类型
    @property (readonly, assign, nonatomic) RLMPropertyType type;
    //管理此结果集合的Realm对象
    @property (readonly, nonatomic) RLMRealm *_Nonnull realm;
    //结果集合中包含的对象的类名称
    @property (readonly, copy, nonatomic, nullable) NSString *objectClassName;
    //返回结果集合中的第一个对象
    - (nullable RLMObjectType)firstObject;
    //返回结果集合中的最后一个对象
    - (nullable RLMObjectType)lastObject;
    //根据索引index获取其中的某个对象
    - (RLMObjectType)objectAtIndex:(NSUInteger)index;
    //根据对象返回其索引
    - (NSUInteger)indexOfObject:(RLMObjectArgument)object;
    //返回与谓词匹配的结果集合中第一个对象的索引
    - (NSUInteger)indexOfObjectWhere:(nonnull NSString *)predicateFormat, ...;
    //返回与结果集合中给定谓词匹配的所有对象
    - (RLMResults<RLMObjectType> *)objectsWhere:(NSString *)predicateFormat, ...;
    //返回RLMResults从现有结果集合中排序的内容
    - (RLMResults<RLMObjectType> *)sortedResultsUsingKeyPath:(NSString *)keyPath ascending:(BOOL)ascending;
    //返回RLMResults与现有结果集合不同的内容
    - (nonnull RLMResults<RLMObjectType> *)distinctResultsUsingKeyPaths:(nonnull NSArray<NSString *> *)keyPaths;
    
    

    相关类的官方说明:https://realm.io/docs/objc/latest/api/Classes.html
    (四)Realm的使用
    1.存储对象
    对于RLMObject类型的对象,我们可以直接对创建的对象进行存储,第一步, 初始化对象

        //1.属性赋值
        Dog *dog1 = [[Dog alloc]init];
        dog1.name = @"perter1";
        dog1.age = 1;
        //将数组转化为对象
        Dog *dog2 = [[Dog alloc]initWithValue:@[@"perter2",@2]];
        //将字典转化成对象
        Dog *dog3 = [[Dog alloc]initWithValue:@{@"name":@"perter3",@"age":@3}];
    
    

    第二步就是把RLMObject对象写入Realm数据库, 同样有三种方式

    //默认数据库
        RLMRealm *realm = [RLMRealm defaultRealm];
        //增
        //第一种增加方式
        [realm beginWriteTransaction];
        [realm addObject:dog1];
        [realm commitWriteTransaction];
        //第二种增加方式
        [realm transactionWithBlock:^{
            [realm addObject:dog2];
            [realm addObject:dog3];
        }];
        //第三种增加方式
        [realm transactionWithBlock:^{
            [Dog createInRealm:realm withValue:@{@"name":@"perter4",@"age":@4}];
        }];
    
    

    Note:如果有多个写入操作,建议将每个写入操作放进一个单独的子线程中
    2.查询操作
    Realm的查询条件可以使用==、<=、<、>=、>、!=、BETWEEN、CONTAINS 以及 ENDSWITH等多种操作符

    //查
        //Realm的查询条件可以使用==、<=、<、>=、>、!=、BETWEEN、CONTAINS 以及 ENDSWITH等多种操作符 关系型运算符
        //第一种:全量查询
        RLMResults *result = [Dog allObjects];
        NSLog(@"查询结果 %@",result);
        Dog *dog5 = [[Dog alloc]initWithValue:@{@"name":@"perter5",@"age":@5}];
        [realm transactionWithBlock:^{
            [realm addObject:dog5];
        }];
        NSLog(@"查询结果 %@",result);//实时查询更新
        //第二种:条件查询
        result = [Dog objectsWhere:@"age < 2"];
        NSLog(@"查询结果 %@",result);
        //第三种:数组排序
        RLMResults *result1 = [result sortedResultsUsingKeyPath:@"age" ascending:YES];
        NSLog(@"查询结果 %@",result1);//对原有数组进行排序之后得到一个新的数组
        //第四种:链式查询
        RLMResults *result2 = [result1 objectsWhere:@"age<3"];
        NSLog(@"查询结果 %@",result2);
    
    

    3.更新操作
    需要修改的模型一定是被Realm所管理的模型, 而且已经和磁盘上的对象进行地址映射

    //更新
        //第一种更改在原有基础上进行更改
        [realm transactionWithBlock:^{
            dog1.name = @"newName1";
            dog2.name = @"newName2";
    
        }];
        RLMResults *result3 = [Dog objectsWhere:@"age < 2"];
        Dog *currentDog = result3.firstObject;
        [realm transactionWithBlock:^{
            currentDog.name = @"titanking";
        }];
        //第二种是有主键的情况下使用 addOrUpdateObject 或则createInRealm 方法进行更新 不然会crash: reason: ''Dog' does not have a primary key and can not be updated'
    //    Dog *dog11 = [[Dog alloc]initWithValue:@{@"name":@"dog11",@"age":@11}];
    //    [realm transactionWithBlock:^{
    //        [realm addOrUpdateObject:dog11];
    //
    //    }];
    //    [realm transactionWithBlock:^{
    //        [Dog createInRealm:realm withValue:@{@"name":@"dog12",@"age":@12}];
    //    }];
    //    RLMResults *result4 = [Dog allObjects];
    //    NSLog(@"查询结果 %@",result4);
    
    

    Note:当有主键的情况下, 使用Update方法
    addOrUpdateObject会去先查找有没有传入的Student相同的主键,如果有,就更新该条数据
    这里需要注意,addOrUpdateObject这个方法不是增量更新,所有的值都必须有,如果有哪几个值是null,那么就会覆盖原来已经有的值,这样就会出现数据丢失的问题
    createOrUpdateInRealm:withValue这个方法是增量更新的,后面传一个字典,使用这个方法的前提是有主键
    方法会先去主键里面找有没有字典里面传入的主键的记录,如果有,就只更新字典里面的子集;如果没有,就新建一条记录
    用addOrUpdateObject 或则createInRealm 方法进行更新前提是必须有主键, 不然会crash: reason: ''Dog' does not have a primary key and can not be updated'
    4.删除操作

    //删除
        //第一种 根据条件查询
        RLMResults *result5 = [Dog objectsWhere:@"age = 1"];
        Dog *deleteDog = [result5 firstObject];
        [realm transactionWithBlock:^{
            [realm deleteObject:deleteDog];
        }];
        RLMResults *result6 = [Dog objectsWhere:@"age < 6"];
        for (Dog *dog in result6) {
            [realm transactionWithBlock:^{
                [realm deleteObject:dog];
            }];
        }
        //如果有主键根据主键进行查询 没有就会crash
    //    Dog *keyDog = [Dog objectInRealm:realm forPrimaryKey:@1];
    //    [realm transactionWithBlock:^{
    //        [realm deleteObject:keyDog];
    //    }];
        ```
    Note:删除方法中涉及到的primaryKey字段的前提是必须有主键
    5.Realm数据库机制
    上面用到的获取realm对象的方式都是通过defaultRealm来获取默认配置的realm对象,而我们想要创建不同的Realm表则通过RLMRealmConfiguration配置进行操作
    
    

    //配置Realm数据库

    [self setDefaultRealmForUser:@"zhangsan"];
    RLMRealm *newRealm = [RLMRealm defaultRealm];
    
    
    -(void)setDefaultRealmForUser:(NSString *)username {
        RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
        config.fileURL = [[[config.fileURL URLByDeletingPathExtension] URLByAppendingPathComponent:username] URLByAppendingPathExtension:@"realm"];
        [RLMRealmConfiguration setDefaultConfiguration:config];
    }
    
    

    6.查看本地Realm数据库
    找到本地Realm的路径,然后直接用Realm Browser 打开就可

    image

    以上几种情况是比较常见的,后期还会有更新补充,如有错误不吝赐教
    感谢大神文档:https://www.jianshu.com/p/f415d07bc446
    FMDB 使用方法:https://www.jianshu.com/p/7958d31c2a97

    作者:123456789q
    链接:https://www.jianshu.com/p/73b1f509a41f
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

          本文标题:FMDB 使用方法【转】

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