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 = @"添加联系人页面";
}

- (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);
            //执行:
            if (sqlite3_step(stmt) == SQLITE_DONE)
            {
                [self.contacts removeObjectAtIndex:indexPath.row];
                [self.tableView reloadData];
            }
            sqlite3_finalize(stmt);
        }
    }
}

#pragma mark - misc
- (void)setup
{
    self.title = @"联系人列表";
    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.绑定后续传入的参数
        //sqlite的 index 是从1开始的!!!
        sqlite3_bind_text(stmt, 1, [contact.name UTF8String], -1, NULL);
        sqlite3_bind_text(stmt, 2, [contact.mobile UTF8String], -1, NULL);
        
        //3.是否执行成功:
        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];
    

    //插入数据:
//    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;
    //将搜索的结果放到一个可变数组中保存:
    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 - 打开数据库
- (void)openDatabase
{
    NSString *filePath = [self filepath];
    
    //创建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 - 析构函数
- (void)dealloc
{
    [self closeDatabase];
}

#pragma mark - 关闭数据库
- (void)closeDatabase
{
    sqlite3_close(_db);
}


#pragma mark - 读取数据库信息
- (void)read
{
    sqlite3_stmt *stmt = NULL;
    //sql语句:
    NSString *sql = @"select * from contacts";
    //第三个参数�一定要写 -1 才行 , 不能瞎逼写...
    if (sqlite3_prepare(_db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
        //SQLITE_ROW:如果执行SQLITE_ROW后面还有其他数据可以再次执行......
        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;
}

愿编程让这个世界更美好

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容