1. 程式人生 > >iOS開發-SQLite資料庫在App專案中的設定及使用

iOS開發-SQLite資料庫在App專案中的設定及使用

在iOS開發中,除了UI頁面以外使用最多的估計是資料物件的儲存了~比如聊天記錄、通訊錄和通訊記錄、瀏覽記錄等等。我們要根據不同的使用方式去對這些資料儲存並使用。常用的有:①沙盒機制 ②屬性列表plist ③SQLite ④CoreData,本文介紹的就是基礎的SQLite的儲存機制,其他的稍後會陸續跟進~

一、首先要注意SQLite的特性:無資料型別的資料庫,所以和在別的平臺上的SQL會有一定的差距

二、常用資料型別

· integer有符號的整數型別

· text字串型別

· real浮點型別

· blob二進位制物件型別

三、在專案中建立資料庫

①在專案中引入sql支援庫:libsqlite3.tbd,還有一個3.0的,我個人用3,不要問我為什麼啊(╯‵□′)╯︵┻━┻

②配置資料庫,建立兩個NSObject類,一個作為model 一個作為資料庫操作


假設我們只儲存兩個資料,一個是又textview寫入的文字,一個是當前時間

DataModel.h檔案
#import <Foundation/Foundation.h>

@interface DataModel : NSObject

// 用來接收文字的屬性
@property (nonatomic , copy)NSString * text;
// 文字儲存時間
@property (nonatomic , strong)NSDate * date;

// 文字初始化
-(id)initWithText:(NSString *)text Date:(NSDate*)date;

@end

DataModel.m檔案
#import "DataModel.h"

@implementation DataModel

-(id)initWithText:(NSString *)text Date:(NSDate*)date{
    self = [super init];
    if (self) {
        self.text = text;
        self.date = date;
    }
    return self;
}

@end
針對資料庫的操作就是通過DBOperation來完成,包括表的建立和資料庫連線以及各項操作
DBOperation.h檔案
#import <Foundation/Foundation.h>
// 引入model
#import "DataModel.h"
// 引入sql的支援庫
#import "sqlite3.h"

// 資料庫檔名
#define DB_Name @"Database.sqlite3"

@interface DBOperation : NSObject
{
    // 資料庫物件的成員變數
    sqlite3 * database;
}

// 建立一個管理器
+ (DBOperation *)DataBaseManager;
// 資料庫檔案路徑
- (NSString *)Documentsfilepath;
// 開啟資料庫、建立資料庫表
- (void)createDataBaseTable;

// 新增
-(int)addData:(DataModel*)model;
// 刪除
-(int)deleteData:(DataModel*)model;
// 修改
-(int)editData:(DataModel*)model;
// 查詢
-(NSMutableArray*)selectall;

@end

DBOperation.m檔案
#import "DBOperation.h"

@implementation DBOperation

// 建立一個靜態變數
static DBOperation * DataBaseManager = nil;

+ (DBOperation*)DataBaseManager
{
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        
        DataBaseManager = [[self alloc] init];
        [DataBaseManager createDataBaseTable];
        
    });
    return DataBaseManager;
}

// 建立一個數據庫,建立名為Text的表設定一個content的屬性
- (void)createDataBaseTable {
    NSString *writableDBPath = [self Documentsfilepath];
    const char* charpath = [writableDBPath UTF8String];
    
    if (sqlite3_open(charpath, &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO,@"資料庫開啟失敗");
    } else {
        char *err;
        // 建立一個數據庫表,名為 Text  並新增兩個元素 其中textdate為主鍵
        NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS Text (textdate TEXT PRIMARY KEY, content TEXT);"];
        const char* charSql = [sql UTF8String];
        
        if (sqlite3_exec(database, charSql,NULL,NULL,&err) != SQLITE_OK) {
            sqlite3_close(database);
            NSAssert(NO, @"建表失敗");
        }
        sqlite3_close(database);
    }
}

// 資料庫存放路徑
- (NSString *)Documentsfilepath {
    NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *path = [documentDirectory stringByAppendingPathComponent:DB_Name];
    
    return path;
}

//新增方法
-(int)addData:(DataModel *)model
{
    
    NSString *path = [self Documentsfilepath];
    const char* charpath = [path UTF8String];
    
    if (sqlite3_open(charpath, &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO,@"資料庫開啟失敗。");
    } else {
        
        NSString *sql = @"INSERT OR REPLACE INTO Text (textdate, content) VALUES (?,?)";
        const char* charSql = [sql UTF8String];
        
        sqlite3_stmt *statement;
        //預處理過程
        if (sqlite3_prepare_v2(database, charSql, -1, &statement, NULL) == SQLITE_OK) {
            
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
            NSString *strDate = [dateFormatter stringFromDate:model.date];
            const char* charDate  = [strDate UTF8String];
            
            const char* charContent = [model.text UTF8String];
            
            //繫結引數開始
            sqlite3_bind_text(statement, 1, charDate, -1, NULL);
            sqlite3_bind_text(statement, 2, charContent, -1, NULL);
            
            //執行插入
            if (sqlite3_step(statement) != SQLITE_DONE) {
                NSAssert(NO, @"插入資料失敗。");
            }
        }
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }
    return 0;
}

//刪除方法
-(int)deleteData:(DataModel *)model
{
    NSString *path = [self Documentsfilepath];
    const char* charpath = [path UTF8String];
    
    if (sqlite3_open(charpath, &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO,@"資料庫開啟失敗。");
    } else {
        NSString *sql = @"DELETE from Text where textdate =?";
        const char* charSql = [sql UTF8String];
        
        sqlite3_stmt *statement;
        //預處理過程
        if (sqlite3_prepare_v2(database, charSql, -1, &statement, NULL) == SQLITE_OK) {
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
            NSString *strDate = [dateFormatter stringFromDate:model.date];
            const char * charDate  = [strDate UTF8String];
            
            //繫結引數開始
            sqlite3_bind_text(statement, 1, charDate, -1, NULL);
            //執行
            if (sqlite3_step(statement) != SQLITE_DONE) {
                NSAssert(NO, @"刪除資料失敗。");
            }
        }
        
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }
    
    return 0;
}

//查詢資料方法
-(NSMutableArray*)selectall
{
    NSMutableArray *listData = [[NSMutableArray alloc] init];
    
    NSString *path = [self Documentsfilepath];
    const char* charpath = [path UTF8String];
    
    if (sqlite3_open(charpath, &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSAssert(NO,@"資料庫開啟失敗。");
    } else {
        
        NSString *sql 
[email protected]
"SELECT textdate,content FROM Text"; const char* charSql = [sql UTF8String]; sqlite3_stmt *statement; //預處理過程 if (sqlite3_prepare_v2(database, charSql, -1, &statement, NULL) == SQLITE_OK) { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; //執行 while (sqlite3_step(statement) == SQLITE_ROW) { char *bufDate = (char *) sqlite3_column_text(statement, 0); NSString *strDate = [[NSString alloc] initWithUTF8String: bufDate]; NSDate *date = [dateFormatter dateFromString:strDate]; char *bufContent = (char *) sqlite3_column_text(statement, 1); NSString * strContent = [[NSString alloc] initWithUTF8String: bufContent]; DataModel * model = [[DataModel alloc] initWithText:strContent Date:date]; [listData addObject:model]; } } sqlite3_finalize(statement); sqlite3_close(database); } return listData; } @end

到目前為止資料庫的處理就是基本完成了,剩下的就是去專案裡面開始實際操作,為了方便寫了一個DBManager用來管理引用資料庫操作和model值得傳遞

DBManager.h檔案
#import <Foundation/Foundation.h>
#import "DataModel.h"
#import "DBOperation.h"

@interface DBManager : NSObject

// 新增
-(NSMutableArray *)addTextdata:(DataModel*)model;
// 刪除
-(NSMutableArray *)deleteTextdata:(DataModel*)model;
// 查詢
-(NSMutableArray *)selectall;

@end

DBManager.m檔案
#import "DBManager.h"
@implementation DBManager

// 這個類是用來作為媒介,可用可不用,只是為了讓過程更加清晰

// 新增
-(NSMutableArray *)addTextdata:(DataModel *)model
{
    DBOperation * m = [DBOperation DataBaseManager];
    [m addData:model];
    return [m selectall];
}
// 刪除
-(NSMutableArray *)deleteTextdata:(DataModel *)model
{
    DBOperation * m = [DBOperation DataBaseManager];
    [m deleteData:model];
    return [m selectall];
}

// 查詢
-(NSMutableArray *)selectall
{
    DBOperation * m = [DBOperation DataBaseManager];
    return [m selectall];
}

@end
③我們回到頁面建立的地方,開始建立檢視,程式碼就不詳細講解了,在附上的demo中有很詳細的註釋,目前就是講一個引導性的思路~在首頁建立一個tableview,用來展示資料,通過nav上的button進入到add頁面,直接呼叫DBManager的add方法,我在這裡添加了一個訊息中心,方便返回頁面時候的傳值。
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton * addbtn = [[UIButton alloc]initWithFrame:CGRectMake(self.view.frame.size.width/2, 100, 120, 30)];
    addbtn.backgroundColor = [UIColor redColor];
    [addbtn setTitle:@"新增" forState:UIControlStateNormal];
    [addbtn addTarget:self action:@selector(add) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:addbtn];
    
    textview = [[UITextView alloc]initWithFrame:CGRectMake(0, 150, self.view.frame.size.width, 100)];
    textview.backgroundColor = [UIColor blueColor];
    [self.view addSubview:textview];
    // Do any additional setup after loading the view.
}

-(void)add{
    
    DBManager *manager = [[DBManager alloc] init];
    DataModel *model = [[DataModel alloc] init];
    model.date = [[NSDate alloc] init];
    model.text = textview.text;
    NSMutableArray *reslist = [manager addTextdata: model];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"backaction" object:reslist userInfo:nil];
    [self dismissViewControllerAnimated:NO completion:nil];
}

在首頁先記得宣告訊息中心
[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reloadView:)
                                                 name:@"backaction"
                                               object:nil];

然後刪除的方法我寫在了tableview的編輯裡面直接完成刪除操作~
// 向左滑動可刪除資料
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        
        DataModel * model = [self.listData objectAtIndex:[indexPath row]];
        DBManager * dm = [[DBManager alloc] init];
        self.listData = [dm deleteTextdata: model];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        
    }
}

四、也許有人會問我為什麼增刪改查沒有“改”這一項,我想說我也不知道啊,如果知道的教教我~哈哈,正常來說都是網路請求的資料儲存到本地做查詢和刪除,修改資料都是直接上傳到伺服器上面。表示沒有做過需要在本地修改的資料庫專案~(╯‵□′)╯︵┻━┻(我是菜雞)

附上傳送門:demo

相關推薦

iOS開發-SQLite資料庫App專案設定使用

在iOS開發中,除了UI頁面以外使用最多的估計是資料物件的儲存了~比如聊天記錄、通訊錄和通訊記錄、瀏覽記錄等等。我們要根據不同的使用方式去對這些資料儲存並使用。常用的有:①沙盒機制 ②屬性列表plist ③SQLite ④CoreData,本文介紹的就是基礎的SQLite

iOS開發之如何在NSURLRequest設定自定義header請求頭

在使用百度API的時候需要在HTTP請求頭中增加一個apikey,後來我查到已經有相關文章了:http://ju.outofmemory.cn/entry/136630 不過此文章寫得讓人有點看不明白,所以我根據此文章重新介紹如何在NSURLRequest設定自定義請求頭

iOS多語言(國際化)開發(跟隨系統 + APP內手動設定)

一:跟隨系統切換語言 1>建立好專案工程後, 新建一個多語言檔案: 2>新增要設定的語言型別: 3>新增成功 細心的朋友可能會發現在English後面寫的是3 Files Localized,這是因為英語是系

ios開發時,在Xcode新增多個targets進行版本控制,管理多個相同內容的專案

 在ios開發時,我們經常會遇到對同一個app開發多個版本(Pro、Lite、Free)的情況,這裡就涉及到xcode裡通過新增多個targets來進行版本控制的問題了,下面就簡單說明一下: 點選左側的工程名稱,右側會出現PROJECT和TARGETS,點選你現在的target,假如叫A,右鍵彈出選單中,選擇

Android開發-SQLite從資原始檔資料庫複製到SD到增刪改查-AndroidStudio

覺得博文有用,請點贊,請評論,請關注,謝謝!~最近換工作了,新專案接觸到一些新的知識點,跟大家逐一分享~~首先是SQLite,專案中需要把一個本地幾十兆的本地資料庫放在專案中,實現只用json傳遞少量資料,卻可以實現複雜資料查詢顯示的功能。我分兩塊來說,一個使用SQLiteS

iOS開發之使用App Store加急審核使用說明

when evel bar develop 修復 ios開發 eth sin mar p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px "PingFang SC"; color

iOS開發技巧之:相簿的GIF圖片的讀取與儲存

大家都知道iOS的系統相簿是不支援gif圖片預覽的。但是,這並不代表系統相簿不能儲存和讀取gif圖片。通過Safari長按gif圖片,選擇儲存到相簿,這時儲存到相簿裡的圖片就是gif的,雖然它不會動。 下面將介紹如何對系統相簿進行gif的讀取與儲存。 什麼是 UTI iOS系統相

iOS 開發之現有老專案引入整合 Flutter

  【Flutter 環境配置傳送門】   1、在工程目錄執行如下命令引入 flutter 配置 flutter create -t module flutter_module 補充:新增 flutter 依賴庫流程: cd flutter_modul

在 Create React App 專案使用 Prettier

前言 如果你只想知道如何在 WebStorm 或 VS Code 中,使用 Prettier 去自動格式化程式碼,那就一拉到底,直奔主題吧。 Prettier 介紹 Prettier 是一個「武斷的」(官網用詞:opinionated)程式碼格式化工具。 它只提供了

Vue專案設定背景圖片方法

 例如css樣式 background:url("../../assets/head.jpg");  1、在data中定義如下: export default { name: 'productdetailspage', data() { return { n

iOS開發之給navigationbar和view設定同一張圖片

###### 效果一: 今天因為這個小東西被吐槽了...但還是決定記錄一下... 其實說是給navigationbar和view設定同一張圖片是不對的,應該是隱藏navigationbar,再去掉statusbar的背景色,新增view 最開始

在vue cli 3生成的專案設定less ,sass, stylus的全域性變數

如題: 其實看官方文件我們知道可以使用style-resources-loader這個loader來設定自動化匯入 在每一個關於stylus的檔案中匯入想要的匯入的檔案,你也可以設定為在每一個sass或者less檔案中匯入 但是這是新增了一條規則,來處理自動化匯入。 有沒有其他方式呢?那就是向前處理器

Mac筆記本是用Idea開發工具在Java專案呼叫python指令碼遇到的環境變數問題解決

問題描述: mac筆記本本身會自帶幾個python版本,比如python2.7版本,我沒有改動mac預設的python版本,只是安裝了python3.7版本。 使用Pycharm開發Python專案沒有遇到什麼問題。但是在java專案中呼叫py指令碼的話,就有問題了。我的專案需要將Pycharm開發好的p

hibernate結合postgresql資料庫專案的使用

新增mvn依賴: <!-- hibernate dependence --> <dependency> <groupId>org.hibernate</groupId> <artifactI

iOS開發 從一個空專案建立ViewController和xib

1、新建一個Empty Application,只選Use Automatic Reference Counting,Use Core Data和Include Unit Tests不選。 2、Command+N 新建檔案,選Cocoa Touch UIViewCont

Vue專案設定背景圖片

在Vue專案開發中我們經常要向頁面中新增背景圖片,可是當我們在樣式中添加了背景圖片後,編譯打包後,配置到伺服器上時,由於路徑解析的問題,圖片並不能夠正確的顯示出來,如下CSS樣式: background:url("../../assets/head.jpg")

iOS開發】判斷app啟動的方式(launchOptions)

iOS app啟動的方式有哪些: 自己啟動(使用者手動點選啟動)urlscheme啟動(關於urlScheme的詳解點選開啟連結)本地通知啟動  (自己寫的本地通知啟動,藍芽模組的啟動,地理圍欄的啟動)遠端通知啟動    (後臺伺服器的推送通知)在appdelegate.m

Apicoud+vue開發高效能商城APP專案實戰教程

第一章:專案概述 001:apicloud平臺介紹。 目前所流行的webapp開發平臺的引入,webapp開發的趨勢和能做的事情。 002:知識體系架構介紹。 vue.js的引入介紹,apicloud模組機制的優勢和選型,開發工具phpstorm和webstorm的推薦使用。 第二章:apicloud快速入

Vue專案設定每個單頁面的標題

兩種實現方法,第一種方法引入外掛,第二種為程式設計方式實現(推薦)首先在路由檔案index.js中給每個單頁面路由新增titleroutes: [{     path: '/',     name: '

vue專案設定全域性變數

跟後端對介面,由於有跨域問題前端設定了代理,但是打包放到伺服器上之後就會出現404問題,原因是這個代理不會在線上環境生效,只是給開發時使用。於是讓後臺更改設定,前端需要直接訪問後臺介面,就需要將後臺地址設為全域性變數,可以在每個元件中直接訪問。查詢記錄方法如下: 1. 單獨新建一個全域性變數模組