数据库之FMDB源码解析二

【iOS】—— FMDB的基础用法 一.基本介绍: 1.简介: 由于iOS中原生的 SQLite API 使用时非常不方便 ,于是就出现了一系列将 SQLite API 进行封装的库,例如FMDB、PlausibleDatabase、sqlitepersistentobjects等,FMDB是一款简洁易用、轻量级的封装库。 2.什么是FMDB: FMDB是iOS平台的SQLite数据库框架。 FMDB以OC的方式封装了SQLite的C语言API。 3.FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。 4.FM 阅读详情

如上一章所讲,FMDB源码主要有以下几个文件组成:

1.FMResultSet : 表示FMDatabase执行查询之后的结果集。

2.FMDatabase : 表示一个单独的SQLite数据库操作实例,通过它可以对数据库进行增删改查等等操作。

3.FMDatabaseAdditions : 扩展FMDatabase类,新增对查询结果只返回单个值的方法进行简化,对表、列是否存在,版本号,校验SQL等等功能。

4.FMDatabaseQueue : 使用串行队列 ,对多线程的操作进行了支持。

5.FMDatabasePool : 使用任务池的形式,对多线程的操作提供支持。(不过官方对这种方式并不推荐使用,优先选择FMDatabaseQueue的方式:ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD)

这一篇我们就来讲讲FMDatabase和FMDatabaseAdditions的实现思路。

FMDatabase源码分析

1.1:打开数据库连接
-(BOOL)open;其实是对sqlite3_open()函数的封装。

- (BOOL)open {
    if (_db) {
        return YES;
    }
    int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db );
    if(err != SQLITE_OK) {
        NSLog(@"error opening!: %d", err);
        return NO;
    }
    //当执行这段代码的时候,数据库正在被其他线程访问,那我们就需要给他设置一个重试时间,默认为2秒。
    if (_maxBusyRetryTimeInterval > 0.0) {
        // set the handler
        [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
    } 
    return YES;
}

- (void)setMaxBusyRetryTimeInterval:(NSTimeInterval)timeout {
    _maxBusyRetryTimeInterval = timeout;
    if (!_db) {
        return;
    }
    if (timeout > 0) {
        sqlite3_busy_handler(_db, &FMDBDatabaseBusyHandler, (__bridge void *)(self));
    }
    else {
        // turn it off otherwise
        sqlite3_busy_handler(_db, nil, nil);
    }
}

setMaxBusyRetryTimeInterval设置重试时间,其实调用的是

int sqlite3_busy_handler(sqlite3*,int()(void,int),void*);

该函数的第一个参数为:需要告知哪一个数据库需要设置busy handler。

第二个参数是需要回调的busy handler,当你调用该回调函数的时候,需要传递给它一个void*的参数拷贝,也就是sqlite3_busy_handler的第三个参数。

另一个需要传给回调函数的int参数表示这次锁事件,该回调函数被调用的次数。

如果回调函数返回0时,将不再尝试再次访问数据库而返回SQLITE_BUSY或者SQLITE_IOERR_BLOCKED.如果回调函数返回非0,将会不断尝试操作数据困。

程序运行过程中,如果有其他进程或者线程在读写数据库,那么sqlite3_busy_handler会不断调用该回调函数,直到其他线程或者进程释放锁。获得锁之后,不会再调用该回调函数,从而继续向下执行下去,进行数据库操作。该函数是在获取不到锁的时候,以执行回调函数的次数来进行延时,等待其他进程或者线程操作数据库结束,从而获得锁进行操作数据库。

2.2:查询数据库
executeQuery系列函数从根本上看其实调用的都是

-(FMResultSet )executeQuery:(NSString )sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args

参数sql : 需要查询的sql语句。

参数arrayArgs : 数组类型的参数。应于于

FMResultSet *resultSet = [_db executeQuery:@"SELECT * FROM t_student WHERE age > ?" withArgumentsInArray:@[@25]];

参数dictionaryArgs:字典类型的参数。应用于

 FMResultSet *resultSet = [_db executeQuery:@"SELECT * FROM t_student WHERE age > :age" withParameterDictionary:@{@"age":@25}];

参数args:可变参数类型。应用于

FMResultSet *resultSet = [_db executeQuery:@"SELECT * FROM t_student WHERE age > ?",@(20)];

下面来看一下该函数的大致实现过程,主要就是对sqlite3_prepare_v2的封装。

- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args {

    if (![self databaseExists]) {//判断数据库是否存在
        return 0x00;
    }

    if (_isExecutingStatement) {//判断数据库是否已经在使用当中
        [self warnInUse];
        return 0x00;
    }

    _isExecutingStatement = YES;

    int rc                  = 0x00;
    sqlite3_stmt *pStmt     = 0x00;
    FMStatement *statement  = 0x00;
    FMResultSet *rs         = 0x00;

    if (_traceExecution && sql) {//打印sql语句
        NSLog(@"%@ executeQuery: %@", self, sql);
    }

    if (_shouldCacheStatements) {//获取缓存数据
        statement = [self cachedStatementForQuery:sql];
        pStmt = statement ? [statement statement] : 0x00;
        [statement reset];
    }

    if (!pStmt) {//没有缓存数据,直接查询数据库

        rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);//对sql语句进行预处理,生成预处理过的“sql语句”pStmt。

        if (SQLITE_OK != rc) {//出错处理
            if (_logsErrors) {
                NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
                NSLog(@"DB Query: %@", sql);
                NSLog(@"DB Path: %@", _databasePath);
            }

            if (_crashOnErrors) {
                NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
                abort();
            }

            sqlite3_finalize(pStmt);
            _isExecutingStatement = NO;
            return nil;
        }
    }

    id obj;
    int idx = 0;
    int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!)//queryCount获取参数个数,“?”或者“:age”都算。

    // If dictionaryArgs is passed in, that means we are using sqlite's named parameter support
    if (dictionaryArgs) {//对dictionaryArgs参数的处理,类似于":age"参数形式

        for (NSString *dictionaryKey in [dictionaryArgs allKeys]) {

            // Prefix the key with a colon.
            NSString *parameterName = [[NSString alloc] initWithFormat:@":%@", dictionaryKey];

            if (_traceExecution) {
                NSLog(@"%@ = %@", parameterName, [dictionaryArgs objectForKey:dictionaryKey]);
            }

            // Get the index for the parameter name.
            int namedIdx = sqlite3_bind_parameter_index(pStmt, [parameterName UTF8String]);

            FMDBRelease(parameterName);

            if (namedIdx > 0) {
                // Standard binding from here.
                // *  将通配符?:age按照索引 赋值为obj。
                //*  SELECT * FROM t_student WHERE age > :age --> SELECT * FROM t_student WHERE age > obj
                [self bindObject:[dictionaryArgs objectForKey:dictionaryKey] toColumn:namedIdx inStatement:pStmt];
                // increment the binding count, so our check below works out
                idx++;
            }
            else {
                NSLog(@"Could not find index for %@", dictionaryKey);
            }
        }
    }
    else {//对于arrayArgs参数和不定参数的处理,类似于"?"参数形式

        while (idx < queryCount) {

            if (arrayArgs && idx < (int)[arrayArgs count]) {//数组形式
                obj = [arrayArgs objectAtIndex:(NSUInteger)idx];
            }
            else if (args) {//不定参数形式
                obj = va_arg(args, id);
            }
            else {
                //We ran out of arguments
                break;
            }

            if (_traceExecution) {
                if ([obj isKindOfClass:[NSData class]]) {
                    NSLog(@"data: %ld bytes", (unsigned long)[(NSData*)obj length]);
                }
                else {
                    NSLog(@"obj: %@", obj);
                }
            }

            idx++;
            // *  将通配符?:age按照索引 赋值为obj。
            //*  SELECT * FROM t_student WHERE age > ? --> SELECT * FROM t_student WHERE age > obj
            [self bindObject:obj toColumn:idx inStatement:pStmt];//绑定参数值
        }
    }

    if (idx != queryCount) {//如果绑定的参数数目不对,则进行出错处理
        NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)");
        sqlite3_finalize(pStmt);
        _isExecutingStatement = NO;
        return nil;
    }

    FMDBRetain(statement); // to balance the release below

    if (!statement) {//生成FMStatement对象
        statement = [[FMStatement alloc] init];
        [statement setStatement:pStmt];

        if (_shouldCacheStatements && sql) {//缓存处理,key为sql语句,值为statement
            [self setCachedStatement:statement forQuery:sql];
        }
    }

    // the statement gets closed in rs's dealloc or [rs close];
    rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self];//生成FMResultSet结果集对象
    [rs setQuery:sql];

    NSValue *openResultSet = [NSValue valueWithNonretainedObject:rs];
    [_openResultSets addObject:openResultSet];

    [statement setUseCount:[statement useCount] + 1];

    FMDBRelease(statement);

    _isExecutingStatement = NO;

    return rs;
}

上面有一个关键的函数就是- (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt进行参数绑定,把通配符形式的参数改成obj实际参数。

将通配符?:age按照索引 赋值为obj。比如:SELECT * FROM t_student WHERE age > :age –> SELECT * FROM t_student WHERE age > obj 或者 SELECT * FROM t_student WHERE age > ? –> SELECT * FROM t_student WHERE age > obj

2.3 更新数据库操作
这里的更新,并不只是单单的更新数据。而是对数据库有更改的操作,增删改都算。FMDB调用的都是executeUpdate系列函数。这个函数基本上跟executeQuery系列函数的实现基本差不多。只是它生成statement对象后,直接调用rc = sqlite3_step(pStmt);更新执行,而没有像executeQuery延迟到FMResultSet中的next函数中执行。
2.4WithFormat形式的数据查询和更新
比如:FMResultSet resultSet = [_db executeQueryWithFormat:@”SELECT FROM t_student WHERE age > %d”,20];替换原来?通配符。

- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... {
    va_list args;
    va_start(args, format);
    NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]];
    NSMutableArray *arguments = [NSMutableArray array];
    [self extractSQL:format argumentsList:args intoString:sql arguments:arguments];
    va_end(args);
    return [self executeQuery:sql withArgumentsInArray:arguments];
}

2.5 一次性执行多条sql语句
使用executeStatements函数可以一次性执行多条sql语句,实例如下:

/**
 *  将多个SQL执行语句写入一个字符串中,并执行
 */
- (void)executeStatementsTest{
    NSString *sql =
    @"CREATE TABLE IF NOT EXISTS t_student_tmp (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, age integer NOT NULL);"
    "INSERT INTO t_student_tmp (name, age) VALUES ('yixiang', 10);"
    "INSERT INTO t_student_tmp (name, age) VALUES ('yixiangXX', 20);";
    BOOL success = [_db executeStatements:sql];
    if (success) {
        NSLog(@"执行成功");
    }else{
        NSLog(@"执行失败");
    }

    sql = @"SELECT * FROM t_student;"
          "SELECT * FROM t_student_tmp;";
    success = [_db executeStatements:sql withResultBlock:^int(NSDictionary *resultsDictionary) {
        NSLog(@"%@",resultsDictionary);//查询结果都在resultsDictionary
        return 0;
    }];
    if (success) {
        NSLog(@"查询成功");
    }else{
        NSLog(@"查询失败");
    }

}

它又是如何实现的呢?他其实就是对sqlite3_exec函数的封装。

- (BOOL)executeStatements:(NSString *)sql withResultBlock:(FMDBExecuteStatementsCallbackBlock)block {

    int rc;
    char *errmsg = nil;

    rc = sqlite3_exec([self sqliteHandle], [sql UTF8String], block ? FMDBExecuteBulkSQLCallback : nil, (__bridge void *)(block), &errmsg);

    if (errmsg && [self logsErrors]) {
        NSLog(@"Error inserting batch: %s", errmsg);
        sqlite3_free(errmsg);
    }

    return (rc == SQLITE_OK);
}

2.6:FMDB的加解密
FMDB中使用- [FMDatabase setKey:]和- [FMDatabase setKeyWithData:]输入数据库密码以求验证用户身份,使用- [FMDatabase rekey:]和- [FMDatabase rekeyWithData:]来给数据库设置密码或者清除密码。这两类函数分别对sqlite3_key和sqlite3_rekey函数进行了封装。

FMDatabaseAdditions源码分析

扩展FMDatabase类,新增对查询结果只返回单个值的方法进行简化,对表、列是否存在,版本号,校验SQL等等功能。
1:XXXForQuery系列函数
对查询结果只有一个值得情况进行优化,有多个值也只取第一个值。用法实例:

/**
 *  使用FMDatabaseAdditions中的intForQuery函数查找数据,如果返回结果有多个数据只取第一条数据
 */
- (void)queryForIntForQuery{
    int idx = [_db intForQuery:@"SELECT id FROM t_student WHERE age = ?",@(26)];
    NSLog(@"%zi",idx);
}

2: 数据库的一些概要信息
-(BOOL)tableExists:(NSString*)tableName;数据库表是否存在。

-(BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName;在tableName表中columnName是否存在。

-(FMResultSet*)getSchema;数据库的一些概要信息。实例如下:

/**
 *schema概要信息
 */
- (void)querySchema{
    //查询数据库schema(所有表的一些信息)
    //*对于表来说, tbl_name 则仍然是表名。 但sqlite_master 中不仅是表记录,还有其它的对象,比如索引,对于索引来说 name 是索引的名字,而tbl_name 是索引所属的表名。
    FMResultSet *resultSet = [_db getSchema];
    while ([resultSet next]) {
        NSString *type = [resultSet stringForColumn:@"type"];
        NSString *name = [resultSet stringForColumn:@"name"];
        NSString *tbl_name = [resultSet stringForColumn:@"tbl_name"];
        int  rootpage = [resultSet intForColumn:@"rootpage"];
        NSString *sql = [resultSet stringForColumn:@"sql"];

        NSLog(@"\n %@ \n %@ \n %@ \n %zi \n %@",type,name,tbl_name,rootpage,sql);
    }

    /**
     *  每一张表具体的概要信息(也就是每一列的信息)
     *  get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
     */
    resultSet = [_db getTableSchema:@"t_student"];
    while ([resultSet next]) {
        int cid = [resultSet intForColumn:@"cid"];
        NSString *name = [resultSet stringForColumn:@"name"];
        NSString *type = [resultSet stringForColumn:@"type"];
        int notnull = [resultSet intForColumn:@"notnull"];
        int pk = [resultSet intForColumn:@"pk"];
        NSLog(@"\n %zi \n %@ \n %@ \n %zi \n %zi",cid,name,type,notnull,pk);
    }
}

3:校验sql语句是否合法

-(BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
C#上位机开发入门:从基础到进阶的全方位指南 C#作为一门现代化编程语言,具备强大的功能和广泛的生态支持,适合用于开发各种类型的上位机应用。通过学习并掌握UI开发、通信协议、多线程编程、数据库操作等技能,你可以打造出稳定、易用、性能优异的上位机软件。 阅读详情

相关推荐

Apache-Plc4x-Modbus-Tcp学习记录(一)

Apache-Plc4x-Modbus-Tcp学习记录(一)

weixin_45325423的博客 6987

IOS开发源码阅读篇--FMDB源码分析2(FMDatabase+FMDatabaseAdditions)

一、前言如上一章所讲,FMDB源码主要有以下几个文件组成: FMResultSet : 表示FMDatabase执行查询之后的结果集。 FMDatabase : 表示一个单独的SQLite数据库操作实例,通过它可以对数据库进行增删改查等等操作。 FMDatabaseAdditions : 扩展FMDatabase类,新增对查询结果只返回单个值的方法进行简化,对表、列是否存在,版本号,校验SQL等等功

yixiangboy的博客 4434

Unidbg补环境实战:复现Shopee风控Native层运行环境

Android App风控已从HTTP层签名校验,演进为深度依赖Native层系统调用与硬件特征的多维验证。其核心原理在于通过JNI桥接Java与Native代码,调用openat、sysconf、getrandom等系统接口读取/proc、/sys、/dev等路径的真实状态,并结合SELinux策略、CPU拓扑、分区哈希等硬性指标构建设备可信画像。这种技术架构显著提升了对抗黑灰产的能力,但也对逆向分析与自动化调用提出更高要求——必须精准模拟底层环境而非仅Hook逻辑。Unidbg补环境正是为此而生:它支持

weixin_30533109的博客 636

数据存储 - FMDB源码分析(FMResultSet)

FMDB是IOS平台的SQLite数据库框架,以OC的方式封装了SQLite的C语言的API。FMDB使用起来更加的面向对象,省去了很多麻烦、冗余的C语言代码具体对比详见我的简书iOS开发数据存储篇—libsqlite3和FMDB的基本使用和区别,对比苹果自带的Core Data框架,更加的轻量级和灵活。提供了多线程安全的数据库操作的方法,有效的防止数据混乱。开源地址。 源码分析 FMDB源...

宋卓的博客 642

MAX31865三线PT100测温实战:配置、接线与代码全解析

本文详细解析MAX31865三线PT100测温的配置、接线与代码实现。通过实战经验分享,介绍如何利用MAX31865芯片实现高精度温度测量,重点讲解三线制接法的自动误差补偿功能,并提供完整的寄存器配置、SPI通信和温度转换算法,帮助开发者快速解决工业测温中的常见问题。

ss78901的博客 757

利用WI生成无线信道数据

选取DeepMIMO的一个射线追踪场景O1(Outdoor 1)Scenario,工作频率为3.5GHz。有两条街和一个十字路口的户外场景18个基站和超过一百万个用户18个基站(BSs):BS1-BS18.每个基站的高度是8米每个基站的天线阵列是isotropic天线三个统一的x-y用户网格用户的总计数量为:1184923每个用户网格中的第一个用户总是(x,y)坐标最低的用户 所有用户的高度是2m每个用户的每个天线阵列是isotropic天线定义射频追踪场景。

bingbingaidaima的博客 5601

【原】FMDB源码阅读(二)

【原】FMDB源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比如FMDB的executeUpdate:系列方法、数据库的加解密等等。这次写的就是对FMDatabase和FMResultSet这两个文件的补全内容。每次写这种补全的内容最头疼,内容会很...

weixin_30782331的博客 155

基于XGBoost的混凝土力学性能预测系统

本文介绍了一个基于XGBoost算法的混凝土力学性能预测系统。该系统通过模拟生成3000组混凝土配合比数据(包含水灰比、水泥用量和龄期三个关键特征),利用XGBoost强大的非线性建模能力预测混凝土抗压强度。研究背景源于传统混凝土性能测试方法耗时耗力的痛点,该系统可显著减少实验次数,优化配合比设计。系统实现包括:数据生成与特征工程(模拟真实工程数据并添加噪声和异常值)、XGBoost模型构建、以及预测性能评估。XGBoost算法因其处理非线性关系能力强、鲁棒性好等优势被选用,可为智能建造和数字化施工提供技术

huanghm88的专栏 128

FMDB

转自:http://www.it165.net/pro/html/201602/61259.html 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于FMDB组件我是一点都没用过。好在FMDB源码中的main.m文件提供了大量的示例,况且网上也有很多最佳实践的例子,我就不在这献丑了。我们先从一个最简单的FMD

ssyyjj88的专栏 1007

使用plot函数可视化F分布累积分布函数数据(R语言)

在上面的代码中,我们使用了seq()函数来生成从0到5之间,以0.1为步长的一组F值。然后,我们指定了分子自由度为3,分母自由度为8,并使用pf()函数计算了对应的F分布CDF值。在本文中,我们将介绍如何使用R语言的plot函数来可视化F分布的累积分布函数(CDF)数据。通过使用plot函数,我们可以直观地了解F分布的累积分布函数,并对F值和对应的累积概率之间的关系有更深入的认识。运行上述代码后,我们将获得一个由F值和对应的累积概率构成的图形,其中x轴表示F值,y轴表示累积概率。

LogicGuruX的博客 502

基于深度学习的茶叶等级检测识别系统:YOLOv10 + UI界面 + 数据集

YOLOv10是YOLO系列的最新版本,继承了YOLO模型的优点,并对速度和精度进行了优化。YOLOv10在目标检测中使用卷积神经网络(CNN)作为基础,通过改进网络结构和优化训练策略,实现了在更低的延迟下进行高精度的目标检测。本文详细介绍了基于YOLOv10的茶叶等级检测与识别系统的设计与实现过程。我们从数据集准备、模型训练与推理、UI界面设计等多个方面进行了详细讲解,并给出了相应的代码实现。通过本系统,我们可以高效地自动检测茶叶的等级,并通过UI界面直观地展示结果。

YOLO 764

iOS开发数据库《六》篇—FMDB源码解析

一、FMDB源码结构 我们可以从结构上看出FMDB在共有5个文件组成,其中FMDB.h用于管理其他5个文件,下面分别讲述5个文件的用处 (1)FMDatabase:代表一个单独的SQLite操作实例,数据库通过它增删改查操作; (2)FMResultSet:代表查询后的结果集; (3)FMDatabaseQueue:代表串行队列,对多线程操作提供了支持; (4)FMDatabaseAdditio...

Z1591090的博客 1522

【AI智能体】Langchain 主流大模型调用与对话API使用详解

【AI大模型】Langchain 模型调用与对话API使用详解

congge_study的博客 406

数据库之FMDB源码解析一

FMDB介绍 FMDB是IOS平台的SQLite数据库框架,以OC的方式封装了SQLite的C语言的API。FMDB使用起来更加的面向对象,省去了很多麻烦、冗余的C语言代码(具体对比详见我的博客iOS开发数据存储篇—libsqlite3和FMDB的基本使用和区别),对比苹果自带的Core Data框架,更加的轻量级和灵活。提供了多线程安全的数据库操作的方法,有效的防止数据混乱。开源地址为http

style_施的藏经阁 592

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

IOS开发源码阅读篇--FMDB源码分析1(FMResultSet)

一、前言FMDB是IOS平台的SQLite数据库框架,以OC的方式封装了SQLite的C语言的API。FMDB使用起来更加的面向对象,省去了很多麻烦、冗余的C语言代码(具体对比详见我的博客IOS开发数据存储篇—libsqlite3和FMDB的基本使用和区别),对比苹果自带的Core Data框架,更加的轻量级和灵活。提供了多线程安全的数据库操作的方法,有效的防止数据混乱。开源地址为https://g

yixiangboy的博客 4257

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

FMDB源码解析

上一篇博客讲述SQLite的使用,本篇将讲述FMDB源码,后面也会讲解SQLite在使用与FMDB的区别。本篇读下来大约20-30分钟,建议大家先收藏一下。 FMDB是以OC方式封装SQLite中C语言的API,也是iOS中SQLite数据库的框架,在目前研发项目中使用的也是比较广泛的。下面直入正题 一、FMDB源码结构 首先我们来看一下FMDB的源码的结构与组成,如下图: ...

weixin_30322405的博客 256

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

FMDB浅析

一、FMDB介绍 FMDB是一种第三方的开源库,FMDB就是对SQLite的API进行了封装,加上了面向对象的思想,让我们不必使用繁琐的C语言API函数,比起直接操作SQLite更加方便。 FMDB优点: 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码 对比苹果自带的CoreData框架,更加轻量级和灵活 提供多线程安全,有效地防止数据混乱,原来的SQLite不...

b5916440的博客 291

FMDB浅析(思想)

http://www.cnblogs.com/OTgiraffe/p/5931800.html 一、FMDB介绍 FMDB是一种第三方的开源库,FMDB就是对SQLite的API进行了封装,加上了面向对象的思想,让我们不必使用繁琐的C语言API函数,比起直接操作SQLite更加方便。 FMDB优点: 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码 对比苹果自带的...

diaoju3333的博客 109

FMDB源码分析

一、前言 如上一章所讲,FMDB源码主要有以下几个文件组成: FMResultSet : 表示FMDatabase执行查询之后的结果集。 FMDatabase : 表示一个单独的SQLite数据库操作实例,通过它可以对数据库进行增删改查等等操作。 FMDatabaseAdditions : 扩展FMDatabase类,新增对查询结果只返回单个值的方法进行简化,对表、列是否存

Linlei的专栏 1167

FMDB数据库连接池终极指南:FMDatabasePool实现原理与最佳实践

FMDB是一款强大的Objective-C SQLite数据库封装库,为iOS和macOS开发者提供了简洁高效的数据库操作接口。在前100个字内,FMDB数据库连接池是FMDB框架中处理多线程数据库访问的核心组件,能够显著提升应用性能和数据安全性。本文将深入解析FMDatabasePool的实现原理,并分享在实际开发中的最佳实践技巧。 ## 📊 为什么需要数据库连接池? 在多线程环境下,直接

gitblog_00524的博客 1075

【原】FMDB源码阅读(一)

【原】FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于FMDB组件我是一点都没用过。好在FMDB源码中的main.m文件提供了大量的示例,况且网上也有很多最佳实践的例子,我就不在这献丑了。我们先从一个最简单的FMDB的例子开始: /...

weixin_30598225的博客 272

iOS学习----------FMDB解析

原文:http://www.cnblogs.com/polobymulberry/p/5178770.html 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于FMDB组件我是一点都没用过。好在FMDB源码中的main.m文件提供了大量的示例,况且网上也有很多最佳实践的例子,我就不在这献丑了。我们先从一个最简单的FMDB的例

yziOS的博客 4468

FMDB 二次封装工具类,让你快速学会封装,集成数据库

来源:StrivEver 链接:http://www.jianshu.com/p/4c77aee0b41c 上个版本为了增加用户体验,部分页面集成了离线缓存数据功能,于是就在项目里使用了数据库管理离线数据。下面交大家一步步学会使用FMDB,以及FMDB的二次封装,同事把我二次封装的数据库放出来,希望能够帮助大家快速学习,集成数据库功能吧。 ...

weixin_30498807的博客 81

iOS开发源码阅读篇--FMDB源码分析3(FMDatabaseQueue+FMDatabasePool)

一、前言如上一章所讲,FMDB源码主要有以下几个文件组成:FMResultSet : 表示FMDatabase执行查询之后的结果集。FMDatabase : 表示一个单独的SQLite数据库操作实例,通过它可以对数据库进行增删改查等等操作。FMDatabaseAdditions : 扩展FMDatabase类,新增对查询结果只返回单个值的方法进行简化,对表、列是否存在,版本号,校验SQL等等功能。...

weixin_33923148的博客 210

iOS开发源码阅读篇--FMDB源码分析1(FMResultSet)

一、前言FMDB是IOS平台的SQLite数据库框架,以OC的方式封装了SQLite的C语言的API。FMDB使用起来更加的面向对象,省去了很多麻烦、冗余的C语言代码具体对比详见我的简书iOS开发数据存储篇—libsqlite3和FMDB的基本使用和区别,对比苹果自带的Core Data框架,更加的轻量级和灵活。提供了多线程安全的数据库操作的方法,有效的防止数据混乱。开源地址为github.com...

weixin_34393428的博客 168

FMDB读取Datetime类型值为1970的问题

1.问题 今天使用FMDB做一个例子程序,新建的一张表有一个datetime字段,数据库有默认值,大概如下 CREATE TABLE [ConsumptionType] ([id] INTEGER PRIMARY KEY NOT NULL ,[name] TEXT,[level] TEXT,[creatdate] DATETIME default (datetim...

weixin_30660027的博客 310
上一篇: iOS中的几种数据存储方式
下一篇: 如何做直播(IJKMediaFramework.framework)
style_施
博客等级 码龄11年 11粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值