SQLite 存儲

效果圖 Gif.gif

Contact.h

#import <Foundation/Foundation.h>
@interface Contact : NSObject

@property (nonatomic,assign)    int64_t     serialId;
@property (nonatomic,copy)      NSString    *name;
@property (nonatomic,copy)      NSString    *mobile;

@end

Contact.m

#import "Contact.h"

@implementation Contact

@end

AddContactViewController.h

#import <UIKit/UIKit.h>
#import "Contact.h"

@protocol AddContactDelegate <NSObject>

- (void)onAddContact:(Contact *)contact;

- (void)onCancel;

@end


@interface AddContactViewController : UIViewController

@property (nonatomic,weak)  id<AddContactDelegate>  delegate;

@end

AddContactViewController.m

#import "AddContactViewController.h"

@interface AddContactViewController ()

@property (weak, nonatomic) IBOutlet UITextField *nameTextfield;

@property (weak, nonatomic) IBOutlet UITextField *mobileTextfield;

@end

@implementation AddContactViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"添加聯(lián)系人頁面";
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
- (IBAction)onCancel:(id)sender {
    if (_delegate && [_delegate respondsToSelector:@selector(onCancel)])
    {
        [_delegate onCancel];
    }
}

- (IBAction)onSave:(id)sender {
    NSString *name = _nameTextfield.text;
    NSString *mobile = _mobileTextfield.text;
    if ([name length] && [mobile length])
    {
        Contact *contact = [[Contact alloc] init];
        contact.name = name;
        contact.mobile = mobile;
        if (_delegate && [_delegate respondsToSelector:@selector(onAddContact:)])
        {
            [_delegate onAddContact:contact];
        }
    }
}

@end

ContactListTableViewController.h

#import <UIKit/UIKit.h>

@interface ContactListTableViewController : UITableViewController

@end

ContactListTableViewController.m

#import "ContactListTableViewController.h"
#import "AddContactViewController.h"
#import <sqlite3.h>


static NSString *contactReuseIdentifier = @"contactReuseIdentifier";


@interface ContactListTableViewController ()<AddContactDelegate,UISearchBarDelegate,UISearchResultsUpdating>

@property (nonatomic,strong)    UISearchController *searchViewController;
@property (nonatomic,copy)      NSMutableArray *contacts;
@property (nonatomic,copy)      NSArray *filteredContacts;
@property (nonatomic,assign)    BOOL shouldShowSearchResult;

@property (nonatomic, assign) sqlite3 *db;

@end

@implementation ContactListTableViewController

- (instancetype)init
{
    if (self = [super init])
    {
        _contacts = [NSMutableArray array];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setup];
    
    [self openDatabase];
    
    [self read];
    
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}


#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.shouldShowSearchResult ? [self.filteredContacts count] : [self.contacts count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:contactReuseIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                      reuseIdentifier:contactReuseIdentifier];
    }
    Contact *contact = self.shouldShowSearchResult ? self.filteredContacts[indexPath.row] : self.contacts[indexPath.row];
    cell.textLabel.text = contact.name;
    cell.detailTextLabel.text = contact.mobile;
    
    return cell;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return self.shouldShowSearchResult == NO;   //搜索結果不做刪除處理
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        int64_t serialId = [self.contacts[indexPath.row] serialId];
        NSString *sql = @"delete from contacts where id = ?";
        sqlite3_stmt *stmt = NULL;
        if (sqlite3_prepare(_db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK)
        {
            //綁定ID從1開始:
            sqlite3_bind_int64(stmt, 1, serialId);
            //執(zhí)行:
            if (sqlite3_step(stmt) == SQLITE_DONE)
            {
                [self.contacts removeObjectAtIndex:indexPath.row];
                [self.tableView reloadData];
            }
            sqlite3_finalize(stmt);
        }
    }
}

#pragma mark - misc
- (void)setup
{
    self.title = @"聯(lián)系人列表";
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"添加"
                                                                              style:UIBarButtonItemStylePlain
                                                                             target:self
                                                                             action:@selector(add:)];
    

    self.searchViewController = [[UISearchController alloc] initWithSearchResultsController:nil];
    self.searchViewController.searchBar.delegate = self;
    self.searchViewController.searchResultsUpdater = self;
    self.tableView.tableHeaderView = self.searchViewController.searchBar;
    
}

- (void)add:(id)sender
{
    AddContactViewController *vc = [[AddContactViewController alloc] init];
    vc.delegate = self;
    [self.navigationController pushViewController:vc animated:YES];
}

#pragma mark - store

/**
 *  獲取一個 documents 文件夾下的文件名;
 
 */
- (NSString *)filepath
{
    NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    return  [documents stringByAppendingPathComponent:@"contacts.db"];
}

#pragma mark - AddContactDelegate
- (void)onCancel
{
    [self.navigationController popViewControllerAnimated:YES];
}



- (void)onAddContact:(Contact *)contact
{
    //聲明結構體指針:
    sqlite3_stmt *stmt = NULL;
    NSString *sql = @"insert into contacts(name , mobile) values(?,?)";
    //1.準備:
    if (sqlite3_prepare(_db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK)
    {
        //2.綁定后續(xù)傳入的參數(shù)
        //sqlite的 index 是從1開始的!!!
        sqlite3_bind_text(stmt, 1, [contact.name UTF8String], -1, NULL);
        sqlite3_bind_text(stmt, 2, [contact.mobile UTF8String], -1, NULL);
        
        //3.是否執(zhí)行成功:
        if (sqlite3_step(stmt) == SQLITE_DONE)
        {
            contact.serialId = sqlite3_last_insert_rowid(_db);
            [self.contacts addObject:contact];
            [self.tableView reloadData];
        }
        //4.清理sql語句:
        sqlite3_finalize(stmt);
    }
    
    
    [self.navigationController popViewControllerAnimated:YES];
    

    //插入數(shù)據(jù):
//    NSString *sql = [NSString stringWithFormat:@"insert into contacts(name , mobile) values('%@' , '%@')",contact.name , contact.mobile];
//    sqlite3_exec(_db, [sql UTF8String], NULL, NULL, NULL);
    
}

#pragma mark - search
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    self.shouldShowSearchResult = YES;
    self.filteredContacts = nil;
    [self.tableView reloadData];
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
    self.shouldShowSearchResult = NO;
    self.filteredContacts = nil;
    [self.tableView reloadData];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    self.shouldShowSearchResult = NO;
    self.filteredContacts = nil;
    [self.tableView reloadData];
}

#pragma mark - ??????????
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
    NSString *text = searchController.searchBar.text;
    //將搜索的結果放到一個可變數(shù)組中保存:
    NSMutableArray *contacts = nil;
    if ([text length]) {
        //轉換字符串:
        NSString *searchText = [NSString stringWithFormat:@"%%%@%%", text];
        contacts = [NSMutableArray array];
        sqlite3_stmt *stmt = NULL;
        //sql語句:
        NSString *sql = @"select * from contacts where name like ? or mobile like ?";
        
        if (sqlite3_prepare(_db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK)
        {
            sqlite3_bind_text(stmt, 1, [searchText UTF8String], -1, NULL);
            sqlite3_bind_text(stmt, 2, [searchText UTF8String], -1, NULL);
            while (sqlite3_step(stmt) == SQLITE_ROW)
            {
                int64_t serialId = sqlite3_column_int64(stmt, 0);
                const char *name = (const char *)sqlite3_column_text(stmt, 1);
                const char *mobile = (const char *)sqlite3_column_text(stmt, 2);
                if (name && mobile) {
                    Contact *contact = [[Contact alloc] init];
                    contact.serialId = serialId;
                    contact.name = [NSString stringWithUTF8String:name];
                    contact.mobile = [NSString stringWithUTF8String:mobile];
                    [contacts addObject:contact];
                }
            }
            sqlite3_finalize(stmt);
        }
    }
    
    self.filteredContacts = contacts;
    [self.tableView reloadData];
}


#pragma mark - 打開數(shù)據(jù)庫
- (void)openDatabase
{
    NSString *filePath = [self filepath];
    
    //創(chuàng)建sqlite表格:
    //所有的sql語句返回的是一個int值:
    //#define SQLITE_OK           0   /* Successful result */
    if ((sqlite3_open([filePath UTF8String], &_db)) == SQLITE_OK)
    {
        //建表:
        //CREATE TABLE member (id integer primary key autoincrement , name text , gender integer , mobile text)
        if (sqlite3_exec(_db, "create table if not exists contacts(id integer primary key autoincrement , name text , mobile text)", NULL, NULL, NULL) != SQLITE_OK)
        {
            NSLog(@"create table failed");
        }
    }
    else
    {
        NSLog(@"open database failed");
    }
    
    sqlite3_open([filePath UTF8String], &_db);
}


#pragma mark - 析構函數(shù)
- (void)dealloc
{
    [self closeDatabase];
}

#pragma mark - 關閉數(shù)據(jù)庫
- (void)closeDatabase
{
    sqlite3_close(_db);
}


#pragma mark - 讀取數(shù)據(jù)庫信息
- (void)read
{
    sqlite3_stmt *stmt = NULL;
    //sql語句:
    NSString *sql = @"select * from contacts";
    //第三個參數(shù)?一定要寫 -1 才行 , 不能瞎逼寫...
    if (sqlite3_prepare(_db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
        //SQLITE_ROW:如果執(zhí)行SQLITE_ROW后面還有其他數(shù)據(jù)可以再次執(zhí)行......
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            int64_t serialId = sqlite3_column_int64(stmt, 0);
            const char *name = (const char *)sqlite3_column_text(stmt, 1);
            const char *mobile = (const char *)sqlite3_column_text(stmt, 2);
            if (name && mobile) {
                Contact *contact = [[Contact alloc] init];
                contact.serialId = serialId;
                contact.name = [NSString stringWithUTF8String:name];
                contact.mobile = [NSString stringWithUTF8String:mobile];
                [self.contacts addObject:contact];
            }
        }
        //清理回收sql:
        sqlite3_finalize(stmt);
    }
    [self.tableView reloadData];
}

@end

AppDelegate.m

#import "AppDelegate.h"
#import "ContactListTableViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    ContactListTableViewController *vc = [[ContactListTableViewController alloc] init];
    UINavigationController *nav =[[UINavigationController alloc] initWithRootViewController:vc];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    return YES;
}

愿編程讓這個世界更美好

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捻浦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旗芬,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捆蜀,死亡現(xiàn)場離奇詭異疮丛,居然都是意外死亡,警方通過查閱死者的電腦和手機辆它,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門誊薄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锰茉,你說我怎么就攤上這事呢蔫。” “怎么了飒筑?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵片吊,是天一觀的道長。 經常有香客問我协屡,道長俏脊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任肤晓,我火速辦了婚禮联予,結果婚禮上,老公的妹妹穿的比我還像新娘材原。我一直安慰自己,他們只是感情好季眷,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布余蟹。 她就那樣靜靜地躺著,像睡著了一般子刮。 火紅的嫁衣襯著肌膚如雪威酒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天挺峡,我揣著相機與錄音葵孤,去河邊找鬼。 笑死橱赠,一個胖子當著我的面吹牛尤仍,可吹牛的內容都是我干的。 我是一名探鬼主播狭姨,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼宰啦,長吁一口氣:“原來是場噩夢啊……” “哼苏遥!你這毒婦竟也來了?” 一聲冷哼從身側響起赡模,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤田炭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后漓柑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體教硫,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年辆布,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞬矩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡谚殊,死狀恐怖丧鸯,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情嫩絮,我是刑警寧澤丛肢,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站剿干,受9級特大地震影響蜂怎,放射性物質發(fā)生泄漏。R本人自食惡果不足惜置尔,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一杠步、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榜轿,春花似錦幽歼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至飞傀,卻和暖如春皇型,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砸烦。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工弃鸦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人幢痘。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓唬格,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子西轩,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容