欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

iOS中Sqlite和FMDB使用詳解

 更新時(shí)間:2022年10月20日 09:46:31   作者:云層之上  
這篇文章主要為大家介紹了iOS中Sqlite和FMDB使用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

本文重點(diǎn)說(shuō)下常用的本地?cái)?shù)據(jù)庫(kù)操作,Sqlite和封裝的FMDB的使用,以及Model的存與取。

效果圖

什么是數(shù)據(jù)庫(kù)

  • 數(shù)據(jù)庫(kù)(Database)是按照數(shù)據(jù)結(jié)構(gòu)來(lái)組織、存儲(chǔ)和管理數(shù)據(jù)的倉(cāng)庫(kù)
  • 數(shù)據(jù)庫(kù)可以分為2大種類 :關(guān)系型數(shù)據(jù)庫(kù)(主流)、對(duì)象型數(shù)據(jù)庫(kù)

iOS中的數(shù)據(jù)存儲(chǔ)方式

  • Plist(NSArray\NSDictionary),只能存儲(chǔ)數(shù)組,字典,但是數(shù)組和字典里面不能有自定義對(duì)象
  • Preference(偏好設(shè)置\NSUserDefaults)
  • NSCoding(NSKeyedArchiver\NSkeyedUnarchiver)
  • SQLite3
  • Core Data (面對(duì)對(duì)象)

什么是SQLite

  • SQLite是一款輕型的嵌入式數(shù)據(jù)庫(kù)
  • 它占用資源非常的低,在嵌入式設(shè)備中,可能只需要幾百K的內(nèi)存就夠了
  • 它的處理速度比Mysql、PostgreSQL這兩款著名的數(shù)據(jù)庫(kù)都還快

調(diào)試軟件使用的是Navicat,支持大部分主流數(shù)據(jù)庫(kù)(包括SQLite) 

SQL語(yǔ)句的種類

數(shù)據(jù)定義語(yǔ)句(DDL:Data Definition Language)

  • 包括create和drop等操作
  • 在數(shù)據(jù)庫(kù)中創(chuàng)建新表或刪除表(create table或 drop table)

數(shù)據(jù)操作語(yǔ)句(DML:Data Manipulation Language)

  • 包括insert(添加)、update(修改)、delete(刪除)等操作

數(shù)據(jù)查詢語(yǔ)句(DQL:Data Query Language)

  • 可以用于查詢獲得表中的數(shù)據(jù)
  • 關(guān)鍵字select是DQL(也是所有SQL)用得最多的操作
  • 其他DQL常用的關(guān)鍵字有where,order by,group by和having

字段類型

SQLite將數(shù)據(jù)劃分為以下幾種存儲(chǔ)類型:

  • integer : 整型值
  • real : 浮點(diǎn)值
  • text : 文本字符串
  • blob : 二進(jìn)制數(shù)據(jù)(比如文件,模型) 實(shí)際上SQLite是無(wú)類型的,就算聲明為integer類型,還是能存儲(chǔ)字符串文本(主鍵除外),建表時(shí)聲明啥類型或者不聲明類型都可以,也就意味著創(chuàng)表語(yǔ)句可以這么寫:create table t_student(name, age); 為了保持良好的編程規(guī)范、方便程序員之間的交流,編寫建表語(yǔ)句的時(shí)候最好加上每個(gè)字段的具體類型

Sqlite使用:

一、創(chuàng)建表

  • create table 表名 (字段名1 字段類型1, 字段名2 字段類型2, …) ;
  • create table if not exists 表名 (字段名1 字段類型1, 字段名2 字段類型2, …)(判斷表是否已存在,不存在則創(chuàng)建) ;

示例:create table t_student (id integer, name text, age inetger, score real) ; 

良好的數(shù)據(jù)庫(kù)編程規(guī)范應(yīng)該要保證每條記錄的唯一性,為此,增加了主鍵約束,也就是說(shuō),每張表都必須有一個(gè)主鍵,用來(lái)標(biāo)識(shí)記錄的唯一性,在創(chuàng)表的時(shí)候用primary key聲明一個(gè)主鍵:

示例:create table t_student (id integer primary key, name text, age integer) ;

主鍵的設(shè)計(jì)原則:

  • 主鍵應(yīng)當(dāng)是對(duì)用戶沒(méi)有意義的
  • 永遠(yuǎn)也不要更新主鍵
  • 主鍵不應(yīng)包含動(dòng)態(tài)變化的數(shù)據(jù)
  • 主鍵應(yīng)當(dāng)由計(jì)算機(jī)自動(dòng)生成

integer類型的id作為t_student表的主鍵。

  • 只要聲明為primary key,就說(shuō)明是一個(gè)主鍵字段
  • 主鍵字段默認(rèn)就包含了not null 和 unique 兩個(gè)約束

如果想要讓主鍵自動(dòng)增長(zhǎng)(必須是integer類型),應(yīng)該增加autoincrement,

示例:create table t_student (id integer primary key autoincrement, name text, age integer) ; 

二、刪表

注意:這個(gè)刪是將整個(gè)表刪除

  • drop table 表名 ;
  • drop table if exists 表名 ;(判斷表是否存在,存在則刪除)

示例:drop table if exists t_student ;

三、增(插入數(shù)據(jù)insert)

  • insert into 表名 (字段1, 字段2, …) values (字段1的值, 字段2的值, …) ;

示例:insert into t_student (name, age) values (‘小虎牙’, 10) ; 數(shù)據(jù)庫(kù)中的字符串內(nèi)容應(yīng)該用單引號(hào) ‘ ’ 括住

四、刪(刪除數(shù)據(jù)delete)

  • delete from 表名 ;

示例:delete from t_student ;

注意:上面的示例會(huì)將t_student表中所有記錄都刪掉

五、改(更新數(shù)據(jù)update)

  • update 表名 set 字段1 = 字段1的值, 字段2 = 字段2的值, … ;

示例:

update t_student set name = ‘rc', age = 18 ; 

注意:上面的示例會(huì)將t_student表中所有記錄的name都改為rc,age都改為18

六、查(查詢數(shù)據(jù)select)

  • select 字段1, 字段2, … from 表名 ; (查詢字段1, 字段2數(shù)據(jù))
  • select * from 表名;(查詢表中所有的字段)

示例 :  select name, age from t_student ;select * from t_student ;

七、條件語(yǔ)句

如果只想更新或者刪除某些固定的記錄,那就必須在DML語(yǔ)句后加上一些條件 條件語(yǔ)句的常見格式

  • where 字段 = 某個(gè)值 ; (不能用兩個(gè) =)
  • where 字段 is 某個(gè)值 ; (is 相當(dāng)于 =)
  • where 字段 != 某個(gè)值 ;
  • where 字段 is not 某個(gè)值 ; (is not 相當(dāng)于 !=)
  • where 字段 > 某個(gè)值 ;
  • where 字段1 = 某個(gè)值 and 字段2 > 某個(gè)值 ; (and相當(dāng)于C語(yǔ)言中的 &&)
  • where 字段1 = 某個(gè)值 or 字段2 = 某個(gè)值 ; (or 相當(dāng)于C語(yǔ)言中的 ||)

示例:

  • 將t_student表中年齡大于10 并且 姓名不等于rc的記錄,年齡都改為 5 update t_student set age = 5 where age > 10 and name != ‘rc’ ;
  • 刪除t_student表中年齡小于等于10 或者 年齡大于30的記錄 delete from t_student where age <= 10 or age > 30 ;
  • 將t_student表中名字等于rc的記錄,score字段的值 都改為 age字段的值 update t_student set score = age where name = ‘rc’ ;

八、起別名

格式:

  • select 字段1 別名 , 字段2 別名 , … from 表名 別名 ;
  • select 字段1 別名, 字段2 as 別名, … from 表名 as 別名 ;
  • select 別名.字段1, 別名.字段2, … from 表名 別名 ;

示例:

  • 給name起個(gè)叫做myname的別名,給age起個(gè)叫做myage的別名 select name myname, age myage from t_student ;
  • 給t_student表起個(gè)別名叫做s,利用s來(lái)引用表中的字段 select s.name, s.age from t_student s ;

九、計(jì)算記錄的數(shù)量

  • select count (字段) from 表名 ;
  • select count ( * ) from 表名 ; 示例:
  • select count (age) from t_student ;
  • select count ( * ) from t_student where score >= 60;

十、排序

按照某個(gè)字段的值,進(jìn)行排序搜索 select * from t_student order by 字段 ; 示例:select * from t_student order by age ;

默認(rèn)是按照升序排序(由小到大),也可以變?yōu)榻敌颍ㄓ纱蟮叫。?降序 :select * from t_student order by age desc ; 升序(默認(rèn)):select * from t_student order by age asc ;

用多個(gè)字段進(jìn)行排序 先按照年齡排序(升序),年齡相等就按照身高排序(降序) 示例:select * from t_student order by age asc, height desc ;

十一、limit

使用limit可以精確地控制查詢結(jié)果的數(shù)量,比如每次只查詢10條數(shù)據(jù)

  • select * from 表名 limit 數(shù)值1, 數(shù)值2 ; 跳過(guò)最前面4條語(yǔ)句,然后取8條記錄 示例:select * from t_student limit 4, 8 ;

limit常用來(lái)做分頁(yè)查詢,比如每頁(yè)固定顯示5條數(shù)據(jù),那么應(yīng)該這樣取數(shù)據(jù)

第1頁(yè):limit 0, 5 第2頁(yè):limit 5, 5 第3頁(yè):limit 10, 5 ... 第n頁(yè):limit 5*(n-1), 5

十二、簡(jiǎn)單約束

建表時(shí)可以給特定的字段設(shè)置一些約束條件,常見的約束有

  • not null :規(guī)定字段的值不能為null
  • unique :規(guī)定字段的值必須唯一
  • 指定字段的默認(rèn)值

建議:盡量給字段設(shè)定嚴(yán)格的約束,以保證數(shù)據(jù)的規(guī)范性

name字段不能為null,并且唯一 age字段不能為null,并且默認(rèn)為1

示例:create table t_student (id integer, name text not null unique, age integer not null default 1) ; 

FMDB使用:

  • FMDB是iOS平臺(tái)的SQLite數(shù)據(jù)庫(kù)框架
  • FMDB以O(shè)C的方式封裝了SQLite的C語(yǔ)言API

優(yōu)點(diǎn):

  • 使用起來(lái)更加面向?qū)ο?,省去了很多麻煩、冗余的C語(yǔ)言代碼
  • 對(duì)比蘋果自帶的Core Data框架,更加輕量級(jí)和靈活
  • 提供了多線程安全的數(shù)據(jù)庫(kù)操作方法,有效地防止數(shù)據(jù)混亂

FMDB

FMDB有三個(gè)主要的類

  • FMDatabase :其對(duì)象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫(kù),用來(lái)執(zhí)行SQL語(yǔ)句
  • FMResultSet :用來(lái)執(zhí)行查詢后的結(jié)果集
  • FMDatabaseQueue :用于在多線程中執(zhí)行多個(gè)查詢或更新,它是線程安全的

打開數(shù)據(jù)庫(kù)

通過(guò)指定SQLite數(shù)據(jù)庫(kù)文件路徑來(lái)創(chuàng)建FMDatabase對(duì)象

FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
    NSLog(@"數(shù)據(jù)庫(kù)打開失??!");
}

文件路徑有三種情況

  • 具體文件路徑 :如果不存在會(huì)自動(dòng)創(chuàng)建
  • 空字符串@"" :會(huì)在臨時(shí)目錄創(chuàng)建一個(gè)空的數(shù)據(jù)庫(kù),當(dāng)FMDatabase連接關(guān)閉時(shí),數(shù)據(jù)庫(kù)文件也被刪除
  • nil :會(huì)創(chuàng)建一個(gè)內(nèi)存中臨時(shí)數(shù)據(jù)庫(kù),當(dāng)FMDatabase連接關(guān)閉時(shí),數(shù)據(jù)庫(kù)會(huì)被銷毀

更新數(shù)據(jù)庫(kù)

在FMDB中,除查詢以外的所有操作,都稱為“更新”,create、drop、insert、update、delete等 使用executeUpdate:方法執(zhí)行更新

- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments

示例 :[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @18, @"rc"]

執(zhí)行查詢

- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
// 查詢數(shù)據(jù)
FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];
// 遍歷結(jié)果集
while ([rs next]) {
    NSString *name = [rs stringForColumn:@"name"];
    int age = [rs intForColumn:@"age"];
    double score = [rs doubleForColumn:@"score"];
}

FMDatabaseQueue

FMDatabase這個(gè)類是線程不安全的,如果在多個(gè)線程中同時(shí)使用一個(gè)FMDatabase實(shí)例,會(huì)造成數(shù)據(jù)混亂等問(wèn)題 為了保證線程安全,F(xiàn)MDB提供方便快捷的FMDatabaseQueue類

// FMDatabaseQueue的創(chuàng)建
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
...
[queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"rc"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
    FMResultSet *rs = [db executeQuery:@"select * from t_student"];
    while ([rs next]) {
        // …
    }
}];

事務(wù)、回滾 : 操作數(shù)據(jù)庫(kù)時(shí),會(huì)出現(xiàn)這種情況:更新10條記錄,當(dāng)更新到第5條時(shí),服務(wù)器宕機(jī)了,后面的麻煩就來(lái)了,我們要每次判斷哪條記錄更新了,哪條記錄沒(méi)更新!這時(shí)候就用到了事務(wù),將更新10條記錄放到一個(gè)事務(wù)中,成功完成所有更新操作時(shí)再提交,只要其中一條記錄更新失敗就回滾,回到初始狀態(tài),簡(jiǎn)單的說(shuō)就是要么全部成功,要么全部不成功!

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"rc"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
    [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
    FMResultSet *rs = [db executeQuery:@"select * from t_student"];
    while ([rs next]) {
        // …
    }
}];
//事務(wù)回滾
*rollback = YES;

對(duì)模型進(jìn)行存取

以頭條新聞為例,一條新聞為一條記錄:

1.先在本地?cái)?shù)據(jù)庫(kù)查找是否存在緩存,存在則顯示緩存的新聞,

2.不存在則去頭條服務(wù)器請(qǐng)求數(shù)據(jù)顯示,同時(shí)緩存

思路很簡(jiǎn)單: 要做到請(qǐng)求了今日頭條的新聞緩存到本地?cái)?shù)據(jù)庫(kù)后,下次打開直接在數(shù)據(jù)庫(kù)取出數(shù)據(jù)后顯示。

兩種情況:

1、直接緩存后天返回的json數(shù)據(jù) ,好處是簡(jiǎn)單,避免了模型轉(zhuǎn)字典的過(guò)程,數(shù)據(jù)原始,但是如果對(duì)數(shù)據(jù)有更新,比如:新聞是否已讀等。

2、將服務(wù)器返回的json轉(zhuǎn)成model(模型)再緩存,缺點(diǎn)就是可能在模型中有為了方便開發(fā)而新增的字段,而這些字段是不需要進(jìn)行緩存的。

第1種比較簡(jiǎn)單,就以第2種為例: 寫了一個(gè)新聞緩存的工具類

NewsCacheTool.h
/**緩存新聞數(shù)據(jù)到本地?cái)?shù)據(jù)庫(kù)*/
+ (void)saveNewsToDatabase:(NSArray *)newsArray;
/**讀取新聞(userID對(duì)應(yīng)用戶的id,同個(gè)應(yīng)用可能存在多個(gè)賬號(hào)登錄情況)*/
+ (NSArray *)selectNewsToDatabase:(NSString *)userID;
/**清除緩存*/
+ (void)clearNewsCache:(void(^)(BOOL success))flag;
NewsCacheTool.m
static FMDatabase *_db;
// 第一次使用就開始創(chuàng)建表
+ (void)initialize{
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
    NSString *filePath = [cachePath stringByAppendingPathComponent:@"News.sqlite"];
    _db = [FMDatabase databaseWithPath:filePath];
    if ([_db open]) {
        NSLog(@"打開數(shù)據(jù)庫(kù)成功");
        // 自增主鍵、userID、二進(jìn)制數(shù)據(jù)流
        NSString *sql = @"create table if not exists t_news (id integer primary key autoincrement,userID text,dict blob);";
        BOOL success = [_db executeUpdate:sql];
        if (success) {
            NSLog(@"創(chuàng)建表成功");
        }else{
            NSLog(@"創(chuàng)建表失敗");
        }
    }else{
        NSLog(@"打開數(shù)據(jù)庫(kù)失敗");
    }
}
// 緩存數(shù)據(jù),這里為了安全起見應(yīng)該使用事務(wù)
+ (void)saveNewsToDatabase:(NSArray *)newsArray{
    // 遍歷模型數(shù)組
    for (NewsModel *nesw in newsArray){
        // 用戶的id應(yīng)該從自己的服務(wù)器取得
        NSString *userID = @"001";
        // 這是模型轉(zhuǎn)字典的,自己用runtime簡(jiǎn)單實(shí)現(xiàn)了,有很多優(yōu)秀的第三方庫(kù)可以使用,自選
        NSDictionary * newsDic = [nesw getDictionayFromModel];
        NSError *error;
        NSData *data;
        if (@available(iOS 11.0, *)){
            data = [NSKeyedArchiver archivedDataWithRootObject:newsDic requiringSecureCoding:YES error:&error];
        }else{
            data = [NSKeyedArchiver archivedDataWithRootObject:newsDic];
        }
        if (data == nil || error) {
            NSLog(@"緩存失敗:%@", error);
            return;
        }
        BOOL success = [_db executeUpdate:@"insert into t_news (userID,dict) values(?,?)",userID,data];
        if (success) {
            NSLog(@"插入成功");
        }else{
            NSLog(@"插入失敗");
        }
    }
}
// 在數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)
+ (NSArray *)selectNewsToDatabase:(NSString *)userID{
    NSString *sql = [NSString stringWithFormat:@"select * from t_news where userID = '%@';",userID];
    FMResultSet *set = [_db executeQuery:sql];
    NSMutableArray *array = [NSMutableArray array];
    while ([set next]) {
        NSData *data = [set dataForColumn:@"dict"];
        NSError *error;
        NSDictionary *dic;
        if (@available(iOS 11.0, *)) {
            dic = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSObject class] fromData:data error:&error];
        } else {
            dic = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        }
        if(dic){
            NewsModel *news = [[NewsModel alloc]initWithDictionary:dic];
            [array addObject:news];
        }
    }
    return array;
}
// 清除新聞緩存
+ (void)clearNewsCache:(void (^)(BOOL success))flag{
    BOOL success = [_db executeUpdate:@"delete from t_news;"];
    if(flag){
        flag(success);
    }
}

模型轉(zhuǎn)字典的過(guò)程中,在NewsModel類中,用runtime簡(jiǎn)單實(shí)現(xiàn)了,實(shí)際開發(fā)中可能會(huì)多層嵌套字典或數(shù)據(jù),市面上有很多成熟優(yōu)秀的輪子,可自行選擇。

SqliteDemo

以上就是iOS中Sqlite和FMDB使用詳解的詳細(xì)內(nèi)容,更多關(guān)于iOS Sqlite FMDB 使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決移動(dòng)端 ios 系統(tǒng)鍵盤遮擋的問(wèn)題

    解決移動(dòng)端 ios 系統(tǒng)鍵盤遮擋的問(wèn)題

    下面小編就為大家分享一篇解決移動(dòng)端 ios 系統(tǒng)鍵盤遮擋的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • iOS 統(tǒng)計(jì)Xcode項(xiàng)目代碼行數(shù)的實(shí)例

    iOS 統(tǒng)計(jì)Xcode項(xiàng)目代碼行數(shù)的實(shí)例

    下面小編就為大家分享一篇iOS 統(tǒng)計(jì)Xcode項(xiàng)目代碼行數(shù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 百度地圖PC端判斷用戶是否在配送范圍內(nèi)

    百度地圖PC端判斷用戶是否在配送范圍內(nèi)

    在pc端設(shè)置商家的配送范圍,用戶在下單時(shí),根據(jù)用戶設(shè)置的配送地點(diǎn)判斷是否在可配送范圍內(nèi),并給用戶相應(yīng)的提示,下面通過(guò)本文給大家分享具有實(shí)現(xiàn)代碼,感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01
  • iOS應(yīng)用中使用AsyncSocket庫(kù)處理Socket通信的用法講解

    iOS應(yīng)用中使用AsyncSocket庫(kù)處理Socket通信的用法講解

    這篇文章主要介紹了iOS應(yīng)用中使用AsyncSocket庫(kù)處理Socket通信的用法講解,AsyncSocket同時(shí)支持TCP和UDP,文中展示了其建立斷開連接及發(fā)送接收消息的操作,very好用,需要的朋友可以參考下
    2016-05-05
  • iOS實(shí)現(xiàn)圖片輪播器

    iOS實(shí)現(xiàn)圖片輪播器

    這篇文章主要為大家詳細(xì)介紹了iOS如何實(shí)現(xiàn)圖片輪播器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式

    IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式

    組合模式,Composite Pattern,是一個(gè)非常巧妙的模式。幾乎所有的面向?qū)ο笙到y(tǒng)都應(yīng)用到了組合模式,接下來(lái)通過(guò)本文給大家介紹IOS設(shè)計(jì)模式之組合設(shè)計(jì)模式,需要的朋友參考下
    2016-02-02
  • IOS安裝CocoaPods詳細(xì)教程

    IOS安裝CocoaPods詳細(xì)教程

    這篇文章主要為大家詳細(xì)介紹了IOS安裝CocoaPods教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • iOS利用CoreImage實(shí)現(xiàn)人臉識(shí)別詳解

    iOS利用CoreImage實(shí)現(xiàn)人臉識(shí)別詳解

    OS的人臉識(shí)別從iOS 5(2011)就有了,不過(guò)一直沒(méi)怎么被關(guān)注過(guò)。人臉識(shí)別API允許開發(fā)者不僅可以檢測(cè)人臉,也可以檢測(cè)到面部的一些特殊屬性,比如說(shuō)微笑或眨眼。下面這篇文章主要給大家介紹了iOS利用CoreImage實(shí)現(xiàn)人臉識(shí)別的相關(guān)資料,需要的朋友可以參考下。
    2017-05-05
  • IOS 波紋進(jìn)度(waveProgress)動(dòng)畫實(shí)現(xiàn)

    IOS 波紋進(jìn)度(waveProgress)動(dòng)畫實(shí)現(xiàn)

    這篇文章主要介紹了IOS 紋進(jìn)度(waveProgress)動(dòng)畫實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • iOS中Runtime的幾種基本用法記錄

    iOS中Runtime的幾種基本用法記錄

    RunTime顧名思義運(yùn)行時(shí),就是系統(tǒng)在運(yùn)行的時(shí)候的一些機(jī)制,最主要的是消息機(jī)制。下面這篇文章主要給大家介紹了關(guān)于iOS中Runtime的幾種基本用法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07

最新評(píng)論