iOS开发之数据存取(三)——FMDB

2023-11-01

FMDB

基本使用

相比于SQLite3来说Core Data存在着诸多优势,它面向对象,开发人员不必过多的关心更多数据库操作知识,同时它基于ObjC操作,书写更加优雅等。但是它本身也存在着一定的限制,例如如果考虑到跨平台,则只能选择SQLite,因为无论是iOS还是Android都可以使用同一个数据库,降低了开发成本和维护成本。其次是当前多数ORM框架都存在的性能问题,因为ORM最终转化为SQL操作,其中牵扯到模型数据转化,其性能自然比不上直接使用SQL操作数据库。那么有没有更好的选择呢?答案就是对SQLite进行封装。

其实通过前面对于SQLite的分析,大家应该已经看到KCDbManager就是对于SQLite封装的结果,开发人员面对的只有SQL和ObjC方法,不用过多libsqlite3的C语言API。但它毕竟只是一个简单的封装,还有更多的细节没有考虑,例如如何处理并发安全性,如何更好的处理事务等。因此,这里推荐使用第三方框架FMDB,整个框架非常轻量级但又不失灵活性,也是很多企业开发的首选。

1.FMDB既然是对于libsqlite3框架的封装,自然使用起来也是类似的,使用前也要打开一个数据库,这个数据库文件存在则直接打开否则会创建并打开。这里FMDB引入了一个MFDatabase对象来表示数据库,打开数据库和后面的数据库操作全部依赖此对象。下面是打开数据库获得MFDatabase对象的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-(void)openDb:(NSString *)dbname{
     //取得数据库保存路径,通常保存沙盒Documents目录
     NSString *directory=[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject];
     NSLog(@ "%@" ,directory);
     NSString *filePath=[directory stringByAppendingPathComponent:dbname];
     //创建FMDatabase对象
     self.database=[FMDatabase databaseWithPath:filePath];
     //打开数据上
     if  ([self.database open]) {
         NSLog(@ "数据库打开成功!" );
     } else {
         NSLog(@ "数据库打开失败!" );
     }
}

注意:dataWithPath中的路径参数一般会选择保存到沙箱中的Documents目录中;如果这个参数设置为nil则数据库会在内存中创建;如果设置为@””则会在沙箱中的临时目录创建,应用程序关闭则文件删除。

2.对于数据库的操作跟前面KCDbManager的封装是类似的,在FMDB中FMDatabase类提供了两个方法executeUpdate:和executeQuery:分别用于执行无返回结果的查询和有返回结果的查询。当然这两个方法有很多的重载这里就不详细解释了。唯一需要指出的是,如果调用有格式化参数的sql语句时,格式化符号使用“?”而不是“%@”、等。下面是两种情况的代码片段:

a.无返回结果

1
2
3
4
5
6
-(void)executeNonQuery:(NSString *)sql{
     //执行更新sql语句,用于插入、修改、删除
     if  (![self.database executeUpdate:sql]) {
         NSLog(@ "执行SQL语句过程中发生错误!" );
     }
}

b.有返回结果

1
2
3
4
5
6
7
8
9
10
11
12
13
-(NSArray *)executeQuery:(NSString *)sql{
     NSMutableArray *array=[NSMutableArray array];
     //执行查询sql语句
     FMResultSet *result= [self.database executeQuery:sql];
     while  (result.next) {
         NSMutableDictionary *dic=[NSMutableDictionary dictionary];
         for  (int i=0; i<result.columnCount; ++i) {
             dic[[result columnNameForIndex:i]]=[result stringForColumnIndex:i];
         }
         [array addObject:dic];
     }
     return  array;
}

对于有返回结果的查询而言,查询完返回一个游标FMResultSet,通过遍历游标进行查询。而且FMDB中提供了大量intForColumn、stringForColumn等方法进行取值。

并发和事务

我们知道直接使用libsqlite3进行数据库操作其实是线程不安全的,如果遇到多个线程同时操作一个表的时候可能会发生意想不到的结果。为了解决这个问题建议在多线程中使用FMDatabaseQueue对象,相比FMDatabase而言,它是线程安全的。

创建FMDatabaseQueue的方法是类似的,调用databaseQueueWithPath:方法即可。注意这里不需要调用打开操作。

1
2
3
4
5
6
7
8
-(void)openDb:(NSString *)dbname{
     //取得数据库保存路径,通常保存沙盒Documents目录
     NSString *directory=[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject];
     NSLog(@ "%@" ,directory);
     NSString *filePath=[directory stringByAppendingPathComponent:dbname];
     //创建FMDatabaseQueue对象
     self.database=[FMDatabaseQueue databaseQueueWithPath:filePath];
}

然后所有的增删改查操作调用FMDatabaseQueue的inDatabase:方法在block中执行操作sql语句即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-(void)executeNonQuery:(NSString *)sql{
     //执行更新sql语句,用于插入、修改、删除
     [self.database inDatabase:^(FMDatabase *db) {
         [db executeQuery:sql];
     }];
}
-(NSArray *)executeQuery:(NSString *)sql{
     NSMutableArray *array=[NSMutableArray array];
     [self.database inDatabase:^(FMDatabase *db) {
         //执行查询sql语句
         FMResultSet *result= [db executeQuery:sql];
         while  (result.next) {
             NSMutableDictionary *dic=[NSMutableDictionary dictionary];
             for  (int i=0; i<result.columnCount; ++i) {
                 dic[[result columnNameForIndex:i]]=[result stringForColumnIndex:i];
             }
             [array addObject:dic];
         }
     }];
     return  array;
}

之所以将事务放到FMDB中去说并不是因为只有FMDB才支持事务,而是因为FMDB将其封装成了几个方法来调用,不用自己写对应的sql而已。其实在在使用libsqlite3操作数据库时也是原生支持事务的(因为这里的事务是基于数据库的,FMDB还是使用的SQLite数据库),只要在执行sql语句前加上“begin transaction;”执行完之后执行“commit transaction;”或者“rollback transaction;”进行提交或回滚即可。另外在Core Data中大家也可以发现,所有的增、删、改操作之后必须调用上下文的保存方法,其实本身就提供了事务的支持,只要不调用保存方法,之前所有的操作是不会提交的。在FMDB中FMDatabase有beginTransaction、commit、rollback三个方法进行开启事务、提交事务和回滚事务。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS开发之数据存取(三)——FMDB 的相关文章

  • 如何在 iOS 上删除配对的蓝牙设备?

    我希望我的应用程序可以删除配对的蓝牙设备 因为如果设备与 iPhone 配对 则该设备无法用于其他设备 我尝试了 CBCentralManager cancelPeripheralConnection 但它不起作用 他们仍然配对 或者还有其
  • 获取 iOS 5 中最后一个重定向的 url?

    有人可以发布最简单的工作代码 当我 GET 请求一个 url 时 它可以获取最后一个重定向的 url nth 吗 我知道我需要使用异步请求 但我无法制定出解决问题的完整工作代码 我正在使用 ios5 因此我可以使用 ios5 中最新添加的异
  • iOS 应用程序和.NET 应用程序之间的通信?

    我有 2 个应用程序 一个是 iOS 应用程序 一个是 NET 应用程序 我希望我的 iOS 应用程序发送一条消息 调用 NET 应用程序的方法 将一些字符串发送到 NET 应用程序以保存到数据库 那么 我的 iOS 应用程序如何与 NET
  • 在 iPad 上的弹出窗口中推送导航视图控制器时动画弹出窗口内容大小

    当包含的 UINavigationController 推送新控制器时 如何让 UIPopoverController 为其大小设置动画 我有一个UIPopover正在显示从UIBarButtonItem在我的 iPad 应用程序中 它包含
  • 如何以编程方式设置 iOS 6/7 Delta

    当我离开 iOS6 时 我正在使用 Xcode 4 6 开发 UISplitView 应用程序 我有设计 现在我迁移到新的 Xcode5 现在我有这样的设计 UINavigationBar 完全重叠我的 UISearchBar Leo Na
  • 尽管遵循以下说明,PWA iOS Splash 仍不显示

    我正在制作 PWA 并尝试显示闪屏 我正在关注这个教程 https developer apple com library archive documentation AppleApplications Reference SafariWe
  • 如何在 iOS 上的视图之间进行展开/收缩转换?

    我正在尝试在 iOS 中制作过渡动画 其中视图或视图控制器似乎扩展以填充整个屏幕 然后在完成后收缩回原来的位置 我不确定这种类型的转换的正式名称是什么 但您可以在 iPad 版 YouTube 应用中查看示例 当您点击网格上的搜索结果缩略图
  • 是否可以?相机 API ios [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想在应用程序中实现一项功能 当用户
  • 在 Alamofire 中快速发送 GET 请求中的 json 对象

    我正在尝试执行一个绑定了 json 对象的 GET 请求 这就是我生成 JSON 对象的方式 let jsonObject String AnyObject ean code type match value 16743799 然后我执行了
  • 更新到 Xcode 7.0.1,项目现在有问题

    因此 我将 Xcode 6 1 版本上传到 iTunes Connect 并且该应用程序获得了批准 现在我正在尝试更新应用程序 我更新到 Xcode 7 0 1 Xcode 给我带来了问题 指出 对于应用程序 我使用了故事板和 Object
  • 即席分发失败

    我在一家大公司工作 正在开发一个适用于 iOS 5 的 iOS 应用程序 分发应用程序的唯一方式是通过临时部署 我拥有自己的服务器已经有一段时间了 由 o2switch 法国托管商 托管 当我开始开发时 我们使用它来部署应用程序以进行 Be
  • 取消交互式 UINavigationController 弹出手势不会调用 UINavigationControllerDelegate 方法

    如果拖动 a 的边缘UIViewController开始交互式流行过渡UINavigationController the UIViewController在电流下方有viewWillAppear 调用 然后是UINavigationCon
  • 将 HTML 字符串加载到 UIWebView 中的延迟

    我在导航控制器中有两个视图控制器 第一个视图控制器有一个带有按钮的菜单 按下此按钮将移动到第二个视图控制器并将 html 字符串加载到 UIWebView 中 没有其他东西被加载到 webview 中 只是一个简单的 NSString 其中
  • iOS 复合谓词

    我正在编写一个具有照片数据库的应用程序 每张照片都有多个与之关联的标签 并且该应用程序有一个带有大量切换的搜索页面 允许用户仅根据他们感兴趣的标签搜索照片 每个标签都存储了integerID 是因为它们对应于外部数据库的 ID 所以我尝试简
  • Facebook 登录 Apple CNA

    问题 是否可以设置 Facebook 登录以在 CNA 中使用 是否为开发人员提供 CNA 文档 您可以使用任何开发人员工具调试 CNA 屏幕吗 Details 我创建了一个使用电子邮件提交表单或 Facebook 登录按钮的强制门户登录页
  • 带约束的 Swift 动画

    是否可以通过改变约束来制作 UIView 动画 基本上 我想要动画myv UIView 具有 x y 高度和宽度约束 使用 UIView animateWithDuration 1 5 通过改变旧的限制 是的 这是可能的 你可以这样做 fu
  • UINavigationController 在后退按钮单击时向下滚动

    我正在开发一个带有多个导航控制器的 iPhone iPad 应用程序 当我在设备处于横向模式时单击视图的后退按钮时 前一个视图会垂直滚动到屏幕中 而不是像往常一样水平滚动 推送动画始终水平工作 正如它应该的那样 是什么导致了这个奇怪的问题
  • AVAudioMixerNode pan 或 AVAudioUnitSamplerstereoPan 属性无法更改 AVAudioEngine 声音输出的左/右平衡

    我有以下代码 它播放单个 MIDI 音符 但我希望能够调整平衡 平移 以便它仅从左扬声器或右扬声器或某些组合中播放 我认为更改 sampler stereoPan 或 engine mainMixerNode pan 也许可以解决问题 但它
  • 在应用程序内启用或禁用 Iphone 推送通知

    我有一个 iPhone 应用程序 可以接收推送通知 目前 我可以通过转到 iPhone 设置 通知来禁用我的应用程序的推送通知 但我想在我的应用程序中添加一个开关或按钮来启用或禁用推送通知 这是可以做到的 因为我在 foursquare i
  • 如何将 NSAppTransportSecurity 添加到 Cordova 项目

    我正在从事一个 ionic cordova 项目 该应用程序需要配置 iOS 9 版本的应用程序传输安全例外 有谁知道如何将以下配置添加到 cordova 项目配置文件中 配置 xml

随机推荐

  • Java基础--接口(Interface)

    有时必须从几个类中派生出一个子类 继承它们所有的属性和方法 但是 Java不支持多重继承 有个接口 就可以得到多重继承的效果 接口 interface 是抽象方法和常量值的定义的集合 从本质上讲 接口是一种特殊的抽象类 这种抽象类中只包含常
  • 结构方程模型

    结构方程模型 SEM 提示 写完文章后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 结构方程模型 SEM 前言 一 什么是结构方程模型 二 在LISREL中使用结构方程模型 1 LISREL介绍 2 LISREL操作 总结 前
  • 2259. 移除指定数字得到的最大结果、字符串

    版本1 class Solution public string removeDigit string number char digit 记录字符出现的位置 int pos0 1 获取第一次字符出现的位置 int i 0 for i lt
  • Keil MDK error :L6031U

    之前编译都是OK 早上重新编译遇到这个样的错误 ASM 2 axf error L6031U Could not open scatter description file ASM 2 sct No such file or directo
  • idea中解决spring配置文件命名空间(namespace)出现红色问题

    在配置dubbo项目时 开始时经常出现dubbo错误 如下图 修改方式已经出现在提示中了 具体这个更改 1 解压dubbo 2 5 4 jar这样的包 具体看你使用的版本 选择 META INF文件夹 解压要到你的目录下 见下图 2 ide
  • imaplib.abort: socket error:EOF 解决方法

    解决方法 设置重复登录 def login self serv None while True try serv imaplib IMAP4 SSL self imap server 993 r d serv login self user
  • ubuntu18安装caffe(CPU)

    1 前言 历时不知多少天 终于在自己电脑上配置好了caffe环境 2 所需环境 1 ubuntu18 04 2 python3 6 默认是只有3 6 3 安装 3 1切换清华源 cp etc apt sources list etc apt
  • chrome浏览器F12调式,修改替换js文件

    在F12模式下 有时可以直接修改js源码 Ctrl S 保存就可以了 但是有时这种方法会不起作用 这里介绍本地替换js的方式 案例 比如csdn想复制别人的一段文字并保留样式 但是字符长度大于140就不起作用了 1 通过右键定位需要修改的j
  • ELK-日志服务【redis-配置使用】

    目录 环境 1 redis配置 2 filebeat配置 3 对接logstash配置 4 验证 5 安全配置 第一种 kibana nginx访问控制 6 第二种 在ES 主节点 配置TLS 7 kibana配置密码 8 logstash
  • 晨光文具去年赚5亿,连2000元都拿来理财

    只要走出学校大门 在不多于500米半径范围内 你都能轻松找到晨光文具的门店 大到一线城市 小到三四线县城 经过20年苦心经营 晨光文具已经做到了这种格局 在这种格局背后 是晨光系7 2万家零售终端的缜密布局 20年来 在国内书写工具以及学生
  • 07:和为给定数

    总时间限制 1000ms 内存限制 65536kB 描述 给出若干个整数 询问其中是否有一对数的和等于给定的数 输入 共三行 第一行是整数n 0 lt n lt 100 000 表示有n个整数 第二行是n个整数 整数的范围是在0到10 8之
  • Linux Suse firewall 查看,关闭,启动

    查看 linux chkconfig list grep i fire 关闭 linux SuSEfirewall2 stop 启动 linux SuSEfirewall2 stop
  • 最小生成树以及Kruskal算法,Prime算法

    一 最小生成树 连通图 在无向图中 若从顶点v1到顶点v2有路径 则称顶点v1与顶点v2是连通的 如果图中任 意一对顶点都是连通的 则称此图为连通图 强连通图 在有向图中 若在每一对顶点vi和vj之间都存在一条从vi到vj的路径 也存在一条
  • 信号处理中简单实用的方法——提取信号中的包络

    一 用希尔伯特变换计算信号的包络 在求某一信号包络时用得最多的是希尔伯特变换 但并不是希尔伯特变换适用于所有信号求包络的情况 这是因为对于包络没有一个很严格的定义 在求包络时不同的情况会有不同的要求 下面将介绍用希尔伯特变换求取信号的包络
  • JVM一个类的加载过程

    七大步骤 具体过程 加载 classpath jar包 网络 某个磁盘位置下的类的class二进制字节流读进来 在内存中生成一个代表这个类的 java lang Class 对象放入元空间 此阶段我们的程序员可以干预 我们可以自定义类加载器
  • java web考试题及答案_2016JAVA-WEB期末复习题库附答案.doc

    1 当访问一个Servlet时 以下Servlet中的哪个方法先被执行 D A destroy B doGet C service D init0 2 假设在myServlet应用中有一个MyServlet类 在web xml文件中对其进行
  • 【leetcode】求两个链表的交点

    求两个链表的交点 c 借助set Definition for singly linked list struct ListNode int val ListNode next ListNode int x val x next NULL
  • 静态时序分析-Multicycle约束

    有时 前端在一些关键路径上的设计 可能会出现两个时钟周期驱动和采样一拍数据 来放松关键路径上的时序 这样的设计在STA约束过程中 如果不放松 会导致Timing违例过大 无法收敛 此时的Timing由前端逻辑实现保证 STA约束即可释放 以
  • 关于VScode引用头文件时一直报错的解决方法

    一 首先看下配置文件 常见的错误原因可能是因为 c cpp properties json 这个文件并没有配置好 可以参考下列的文件 在这里插入代 configurations name Win32 includePath workspac
  • iOS开发之数据存取(三)——FMDB

    FMDB 基本使用 相比于SQLite3来说Core Data存在着诸多优势 它面向对象 开发人员不必过多的关心更多数据库操作知识 同时它基于ObjC操作 书写更加优雅等 但是它本身也存在着一定的限制 例如如果考虑到跨平台 则只能选择SQL