iOS FMDB框架 数据库使用

之前项目中使用的是CoraData,发现每次的更新数据库中新的属性会非常的麻烦,这里正好尝试着使用一下 FMDB。写了一个FMDB基本用法(增加、删除、查询)的Demo,修改的代码后续会加上。先贴上github连接地址 Demo地址 ,OSChina连接地址 OSChina连接

看一下实现效果
iOS FMDB框架 数据库使用_第1张图片
1111.gif
注意点
  • 这篇文章适合初次使用FDMB者,已经掌握了FMDB使用方法的,就不需要看了。
  • 在做增删改查的时候 VALUES都是对象,Demo中我为了使用的方便都用了String类型
  • 在FMDB这个开源库中,使用到的增、删、改都是更新的动作
  • 为了方便操作写一个管理类,主要用来管理数据库创建,数据表的创建查询,这里以学生管理为例。上代码:
先来看一下管理类的.m文件
#import 
@class Student;
@interface StudentManager : NSObject

//因为在很多地方都需要用到,在这里我使用单利设计
+ (StudentManager *)shareManager;
//创建数据库
- (void)createDatabase;
//添加学生,传入的是学生对象
- (void)insertStudent:(Student *)student;
//添加学生,这里传入的是学生的ID
- (void)addStudentWithStudentId:(NSString *)studentId;
//通过学生的ID删除某一个学生
- (void)deleteStudentWithStudentId:(NSString *)studentId;
//根据某个ID查询该学生是否存在
- (NSArray *)findStudentWithId:(NSString *)studentId;
//这个主要是添加学生的时候,判断这个学生是否已经存在
- (BOOL)isStudentExist:(NSString *)studentId;
//查询所有的学生,并返回
- (NSMutableArray *)findAllStudents;
// 删除所有的学生
- (void)clearAllStudents;
@end
  • 既然是管理,那就要所有关于数据库的操作在这一个类中完成
下面看一下具体的实现.m文件
#import "StudentManager.h"
#import "Student.h"
#import "FMDB.h"

static NSString *const kStudentDB = @"Students.sqlite";
static NSString *const kStudentTable = @"student";

@interface StudentManager ()

@property (nonatomic, copy) NSString *dbPathName;
@property (nonatomic, strong) FMDatabase *database;

@end

@implementation StudentManager

+ (StudentManager *)shareManager {
    static StudentManager *shareManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareManager = [[StudentManager alloc] init];
    });
    return shareManager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        NSInteger status = [self initStudentDBWithDBName:kStudentDB];
        if (status == -1) {
            //失败
            NSLog(@"database name 为空");
        }
        else {
            //创建数据库 或者 已经存在
        }
    }
    return self;
}

//初始化数据库
- (NSInteger)initStudentDBWithDBName:(NSString *)dbName {
    if (!dbName) {
        NSLog(@"数据库名称为空");
        return -1;//初始化数据库失败
    }
    //将数据库保存在沙盒路径下
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];;
    self.dbPathName = [documentPath stringByAppendingFormat:@"/%@", dbName];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isExist = [fileManager fileExistsAtPath:self.dbPathName];
    if (!isExist) {
        NSLog(@"need create database");
        [self connectDB];
        return 0;//不存在需要创建
    }
    else {
        NSLog(@"database is exist");
        return 1;//已经存在
    }
}

//连接数据库
- (void)connectDB {
    if (!_database) {
        //创建
        _database = [[FMDatabase alloc] initWithPath:self.dbPathName];
    }
    if (![_database open]) {
        NSLog(@"打开数据库失败");
    }
    else {
    }
}

//关闭数据库
- (void)closeDB {
    BOOL isClose = [_database close];
    if (isClose) {
        NSLog(@"关闭成功");
    }
}

//创建数据库
- (void)createDatabase {
    //查找数据库所有的表 并且表的名称为 kStudentDB的数据库
    NSString *query = [NSString stringWithFormat:@"select count(*) from sqlite_master where type = 'table' and name = %@", kStudentTable];
    FMResultSet *resultSet = [self.database executeQuery:query];
    [resultSet next];
    NSInteger count = [resultSet intForColumnIndex:0];
    //对count进行bool转化
    BOOL existTable = !!count;
    if (existTable) {
        //数据表已经存在 是否更新数据库
        NSLog(@"数据库已经存在");
    } else {
        //插入新的数据库 @"CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, age integer NOT NULL);"
        NSString *sqlString = @"CREATE TABLE IF NOT EXISTS student (id integer PRIMARY KEY AUTOINCREMENT NOT NULL, student_id text NOT NULL, stu_name VARCHAR(20), stu_score VARCHAR(20))";
        BOOL result = [self.database executeUpdate:sqlString];
        if (!result) {
            NSLog(@"数据表创建失败");
        }
        else {
            NSLog(@"数据表创建成功");
        }
    }
}

//删除某个学生
- (void)deleteStudentWithStudentId:(NSString *)studentId {
    [self.database open];
    NSString *sqlQuery = [NSString stringWithFormat:@"DELETE FROM student WHERE student_id=%@", studentId];
    BOOL result = [self.database executeUpdate:sqlQuery];
    if (result) {
        NSLog(@"从数据库删除学生成功!");
    }
    [self.database close];
}

//插入某个学生
- (void)insertStudent:(Student *)student {
    [self.database open];
    NSMutableString *sqlQuery = [NSMutableString stringWithFormat:@"INSERT INTO student (student_id, stu_name, stu_score) VALUES(?,?,?)"];
    NSString *stuId = [NSString stringWithFormat:@"%@", student.studentId];
    NSLog(@"student = %@ %@ %@", student.name, stuId, student.score);
    BOOL result = [self.database executeUpdate:sqlQuery withArgumentsInArray:@[stuId,student.name, student.score]];
//    BOOL result = [self.database executeUpdate:sqlQuery, student.studentId, student.name, student.score];
    if (result) {
        NSLog(@"inser student succeed!");
        [self.database close];
    }
    else {
        NSLog(@"inser student failure!");
        [self.database close];
    }
}

//添加某个学生Id
- (void)addStudentWithStudentId:(NSString *)studentId {
    [self.database open];
    NSMutableString *query = [NSMutableString stringWithFormat:@"INSERT INTO student"];
    NSMutableString *keys = [NSMutableString stringWithFormat:@" ("];
    NSMutableString *values = [NSMutableString stringWithFormat:@" ( "];
    NSMutableArray *arrguments = [NSMutableArray array];
    if (studentId) {
        [keys appendString:@"student_id,"];
        [values appendString:@"?,"];
        [arrguments addObject:studentId];
    }
    [keys appendString:@")"];
    [values appendString:@")"];
    [query appendFormat:@" %@ VALUES %@", [keys stringByReplacingOccurrencesOfString:@",)" withString:@")"], [values stringByReplacingOccurrencesOfString:@",)" withString:@")"]];
    NSLog(@"query = %@", query);
    [self.database executeUpdate:query withArgumentsInArray:arrguments];
    [self.database close];
}

//清空全部数据
- (void)clearAllStudents {
    [self.database open];
    NSString *query = @"DELETE FROM student";
    BOOL result = [self.database executeUpdate:query];
    if (result) {
        NSLog(@"删除所有学生成功");
    }
    else {
         NSLog(@"删除所有学生失败");
    }
    [self.database close];
}

//查询所有的学生
- (NSMutableArray *)findAllStudents {
    [self.database open];
    NSString *sqlString = @"SELECT student_id, stu_name, stu_score FROM student";
    FMResultSet *resultSet = [self.database executeQuery:sqlString];
    NSMutableArray *array = [NSMutableArray array];
    while ([resultSet next]) {
        Student *stu = [Student new];
        stu.studentId = [resultSet stringForColumn:@"student_id"];
        stu.name = [resultSet stringForColumn:@"stu_name"];
        stu.score = [resultSet stringForColumn:@"stu_score"];
        [array addObject:stu];
    }
    [resultSet close];
    [self.database close];
    return array;
}

//查询某一个学生
- (NSArray *)findStudentWithId:(NSString *)studentId {
    [self.database open];
    NSString *sqlQuery = [NSString stringWithFormat:@"SELECT student_id FROM student WHERE student_id = %@", studentId];
    FMResultSet *resultSet = [self.database executeQuery:sqlQuery];
    NSMutableArray *array = [NSMutableArray array];
    while ([resultSet next]) {
        Student *stu = [Student new];
        stu.studentId = [resultSet stringForColumn:@"student_id"];
        [array addObject:stu];
    }
    [resultSet close];
    [self.database close];
    return array;
}

//判断这个学生是否已经存在
- (BOOL)isStudentExist:(NSString *)studentId {
    [self.database open];
    if ([self findStudentWithId:studentId].count > 0) {
        [self.database close];
        return YES;
    } else {
        [self.database close];
        return NO;
    }
}

定义好了管理的类,下面就要开始使用了
  • 管理的类已经定义好了,使用起来就非常的简单了,一行代码实现增删该查,废话不多说,上代码
#import "StudentListController.h"
#import "Student.h"
#import "StudentManager.h"
#import "StudentInfoCell.h"

typedef NS_ENUM(NSInteger, AlertTextFieldTag) {
    AlertTextFieldStudentNameTag = 10,
    AlertTextFieldStudentIdTag,
    AlertTextFieldStudentScoreTag
};

static NSString *const kStudentInfoCell = @"StudentInfoCell";

@interface StudentListController () {
    Student *addStu;//添加的学生
}

@property (nonatomic, strong) NSMutableArray *students;
@property (nonatomic, assign) AlertTextFieldTag textFieldTag;

@end

@implementation StudentListController

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"FMDBTestDemo";
    UIBarButtonItem *backItem = [[UIBarButtonItem alloc]
                        initWithImage:[[UIImage imageNamed:@"back_navigation"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
                                style:UIBarButtonItemStylePlain
                               target:self
                               action:@selector(back:)];
    self.navigationItem.leftBarButtonItem = backItem;
    UIBarButtonItem *insertItem = [[UIBarButtonItem alloc]
                                 initWithImage:[[UIImage imageNamed:@"mine_profile"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
                                 style:UIBarButtonItemStylePlain
                                 target:self
                                 action:@selector(insertAStudent:)];
    self.navigationItem.rightBarButtonItem = insertItem;
    //获取所有的学生
    self.students = [[StudentManager shareManager] findAllStudents];
    //register cell
    [self.tableView registerNib:[UINib nibWithNibName:kStudentInfoCell bundle:nil] forCellReuseIdentifier:kStudentInfoCell];
    //初始化添加学生的全局变量
    addStu = [Student new];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];

}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.students.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    StudentInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:kStudentInfoCell];
    Student *student = (Student *)self.students[indexPath.row];
    [cell configCellWithStudent:student];

    return cell;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
//        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {

    }   
}

#pragma mark - Table view delegate

- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {

    __weak typeof(self) weakSelf = self;
    UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        NSLog(@"删除数据");
        [weakSelf.students removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
        Student *student = (Student *)weakSelf.students[indexPath.row];
        [[StudentManager shareManager] deleteStudentWithStudentId:student.studentId];
    }];
    deleteAction.backgroundColor = [UIColor redColor];

    UITableViewRowAction *addAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"标记" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        NSLog(@"标记成功");
    }];
    addAction.backgroundColor = [UIColor orangeColor];
    return @[addAction, deleteAction];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 80.0;
}

#pragma mark - Button Action

- (void)insertAStudent:(id)sender {
    __weak typeof(self) weakSelf = self;
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"手动录入" message:@"请输入学生姓名、学号、考试分数" preferredStyle:UIAlertControllerStyleAlert];
    [alertVC addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"学生姓名";
        textField.tag = AlertTextFieldStudentNameTag;
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidchanged:) name:UITextFieldTextDidChangeNotification object:textField];
    }];
    [alertVC addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"学生学号";
        textField.tag = AlertTextFieldStudentIdTag;
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidchanged:) name:UITextFieldTextDidChangeNotification object:textField];
    }];
    [alertVC addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"学生成绩";
        textField.tag = AlertTextFieldStudentScoreTag;
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidchanged:) name:UITextFieldTextDidChangeNotification object:textField];
    }];
    //取消
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
    }];
    [alertVC addAction:cancelAction];
    //确定
    UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[StudentManager shareManager] insertStudent:addStu];
        [self.students addObject:addStu];
        [weakSelf.tableView reloadData];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
    }];
    confirmAction.enabled = NO;
    [alertVC addAction:confirmAction];
    [self presentViewController:alertVC animated:YES completion:nil];
}

- (void)back:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}

#pragma mark - Notification 
- (void)textDidchanged:(NSNotification *)notification {
    UITextField *textField = (UITextField *)notification.object;
    NSInteger textFieldTag = textField.tag;
    UIAlertController *alertVC = (UIAlertController *)self.presentedViewController;//拿到弹出的Alertcontroller
    if (alertVC) {
        if (textFieldTag == AlertTextFieldStudentNameTag) {
            UITextField *stuNameTextField = [alertVC.textFields objectAtIndex:0];
            if (stuNameTextField.text.length > 0) {
                addStu.name = stuNameTextField.text;
            }
            else {
                NSLog(@"学生名称为空");
            }
        } else if (textFieldTag == AlertTextFieldStudentIdTag) {
            UITextField *stuIdTextField = [alertVC.textFields objectAtIndex:1];
            if (stuIdTextField.text.length > 0) {
                addStu.studentId = stuIdTextField.text;
            }
            else {
                NSLog(@"学生名称为空");
            }
        } else if (textFieldTag == AlertTextFieldStudentScoreTag) {
            UITextField *stuScoreTextField = [alertVC.textFields objectAtIndex:2];
            if (stuScoreTextField.text.length > 0) {
                addStu.score = stuScoreTextField.text;
            }
        }
        else {
            NSLog(@"无效的tag");
        }
        if (addStu.name.length > 0
            && addStu.studentId.length > 0 && addStu.score.length > 0) {
            UIAlertAction *confirmAction = alertVC.actions.lastObject;
            confirmAction.enabled = YES;
        }
    }
}

FMDB库的基本使用到这里就结束了。如有使用不正确的地方,请指正。再次附上Demo代码

你可能感兴趣的:(iOS FMDB框架 数据库使用)