import Foundation //Sqlite数据库,需要添加 libsqlite3.tbd 的库,然后创建 .h 头文件,并在头文件中引入 #import "sqlite3.h" //.h 头文件,简单作法:可以先创建一个OC的文件,会提示是否创建头文件,点击确定创建后,头文件会自动创建 class NoteModelSQlite: NSObject { //定义数据库文件名称的常量 let DB_FILE = "/NotesList.sqlite3" //sqlitedb指针 Swift COpaquePointer var db:OpaquePointer? = nil let dateFormatter : DateFormatter = DateFormatter() private static let sharedInstance = NoteModelSQlite() //单例的实例保存这个属性中 class var sharedFoo: NoteModelSQlite { //swift中的静态计算属性 //初始化 sharedInstance.plistCopyDocument() return sharedInstance } //修改Note方法 public func modify(model: Note) { //得到数据库的文件路径 let path:NSString = self.getDocumentPath() as NSString //将path:NSString转换为C的字符串(char*) let cpath = path.cString(using: String.Encoding.utf8.rawValue) /*1、sqlite3_open,打开数据库,如果数据库文件不存在则创建,存在则打开 @param1 文件路径, @param2 db指针类型 &db是传递db地址*/ if sqlite3_open(cpath, &db) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "数据库连接失败" ) } else { let sql = "update note set content = ? where cdate = ?" //sql语句 //sql语句也需要转换成C的字符串 let cSql = sql.cString(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) var statement : OpaquePointer? = nil //statement指针对象 /*2、使用sqlite3_prepare_v2函数预处理SQL语句; @param1 db指针 @param2 要执行的sql语句 @param3 要传递sql语句的大小,传递所有 -1 @param4 statement指针对象 @param5 会告诉你那此没有被传递sql语句 */ if sqlite3_prepare_v2(db, cSql, -1, &statement, nil) == SQLITE_OK { //3、使用sqlite3_bind_text函数绑定参数;sql语句中的条件会用 ? 号来代替 self.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" let strDate = self.dateFormatter.string(from: model. Date as Date ) //把model.Date转为字符串 let cDate = strDate.cString(using: String.Encoding.utf8) //转换为C的字符串(char*) let cContent = model.Content.cString(using: String.Encoding.utf8.rawValue) //转换为C的字符串(char*) /* sqlite3_bind_text 绑定参数 @param1 statement指针对象 @param2 绑定参数的索引 1开始 @param3 正真要绑定的参数 @param4 要传递的最大字节数 @param5 回调函数 */ sqlite3_bind_text(statement, 1, cContent, -1, nil) //绑定content sqlite3_bind_text(statement, 2, cDate, -1, nil) //绑定cdate //4、使用sqlite3_step函数执行SQL语句,遍历结果集; if sqlite3_step(statement) != SQLITE_DONE { //如果没有执行完成 sqlite3_close(db) //关闭链接 assert(false, "信息修改失败" ) } } // 6、使用sqlite3_finalize和sqlite3_close函数释放资源。 sqlite3_finalize(statement) //释放sql语句对象 sqlite3_close(db) } } //插入Note方法 public func create(model: Note) { //得到数据库的文件路径 let path:NSString = self.getDocumentPath() as NSString //将path:NSString转换为C的字符串(char*) let cpath = path.cString(using: String.Encoding.utf8.rawValue) /*1、sqlite3_open,打开数据库,如果数据库文件不存在则创建,存在则打开 @param1 文件路径, @param2 db指针类型 &db是传递db地址*/ if sqlite3_open(cpath, &db) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "数据库连接失败" ) } else { let sql = "insert into note (cdate,content) values (?,?)" //sql语句 //sql语句也需要转换成C的字符串 let cSql = sql.cString(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) var statement : OpaquePointer? = nil //statement指针对象 /*2、使用sqlite3_prepare_v2函数预处理SQL语句; @param1 db指针 @param2 要执行的sql语句 @param3 要传递sql语句的大小,传递所有 -1 @param4 statement指针对象 @param5 会告诉你那此没有被传递sql语句 */ if sqlite3_prepare_v2(db, cSql, -1, &statement, nil) == SQLITE_OK { //3、使用sqlite3_bind_text函数绑定参数;sql语句中的条件会用 ? 号来代替 self.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" let strDate = self.dateFormatter.string(from: model. Date as Date ) //把model.Date转为字符串 let cDate = strDate.cString(using: String.Encoding.utf8) //转换为C的字符串(char*) let cContent = model.Content.cString(using: String.Encoding.utf8.rawValue) //转换为C的字符串(char*) /* sqlite3_bind_text 绑定参数 @param1 statement指针对象 @param2 绑定参数的索引 1开始 @param3 正真要绑定的参数 @param4 要传递的最大字节数 @param5 回调函数 */ sqlite3_bind_text(statement, 1, cDate, -1, nil) //绑定cdate sqlite3_bind_text(statement, 2, cContent, -1, nil) //绑定content //4、使用sqlite3_step函数执行SQL语句,遍历结果集; if sqlite3_step(statement) != SQLITE_DONE { //如果没有执行完成 sqlite3_close(db) //关闭链接 assert(false, "信息添加失败" ) } } // 6、使用sqlite3_finalize和sqlite3_close函数释放资源。 sqlite3_finalize(statement) //释放sql语句对象 sqlite3_close(db) } } //删除Note方法 public func remove(model: Note) { //得到数据库的文件路径 let path:NSString = self.getDocumentPath() as NSString //将path:NSString转换为C的字符串(char*) let cpath = path.cString(using: String.Encoding.utf8.rawValue) /*1、sqlite3_open,打开数据库,如果数据库文件不存在则创建,存在则打开 @param1 文件路径, @param2 db指针类型 &db是传递db地址*/ if sqlite3_open(cpath, &db) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "数据库连接失败" ) } else { let sql = "delete from note where cdate = ?" //sql语句 //sql语句也需要转换成C的字符串 let cSql = sql.cString(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) var statement : OpaquePointer? = nil //statement指针对象 /*2、使用sqlite3_prepare_v2函数预处理SQL语句; @param1 db指针 @param2 要执行的sql语句 @param3 要传递sql语句的大小,传递所有 -1 @param4 statement指针对象 @param5 会告诉你那此没有被传递sql语句 */ if sqlite3_prepare_v2(db, cSql, -1, &statement, nil) == SQLITE_OK { //3、使用sqlite3_bind_text函数绑定参数;sql语句中的条件会用 ? 号来代替 self.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" let strDate = self.dateFormatter.string(from: model. Date as Date ) //把model.Date转为字符串 let cDate = strDate.cString(using: String.Encoding.utf8) //转换为C的字符串(char*) /* sqlite3_bind_text 绑定参数 @param1 statement指针对象 @param2 绑定参数的索引 1开始 @param3 正真要绑定的参数 @param4 要传递的最大字节数 @param5 回调函数 */ sqlite3_bind_text(statement, 1, cDate, -1, nil) //绑定cdate //4、使用sqlite3_step函数执行SQL语句,遍历结果集; if sqlite3_step(statement) != SQLITE_DONE { //如果没有执行完成 sqlite3_close(db) //关闭链接 assert(false, "数据库删除失败" ) } } // 6、使用sqlite3_finalize和sqlite3_close函数释放资源。 sqlite3_finalize(statement) //释放sql语句对象 sqlite3_close(db) } } //根据主键查询一条数据 func findByid(model:Note) -> Note? { //得到数据库的文件路径 let path:NSString = self.getDocumentPath() as NSString //将path:NSString转换为C的字符串(char*) let cpath = path.cString(using: String.Encoding.utf8.rawValue) /*1、sqlite3_open,打开数据库,如果数据库文件不存在则创建,存在则打开 @param1 文件路径, @param2 db指针类型 &db是传递db地址*/ if sqlite3_open(cpath, &db) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "数据库连接失败" ) } else { let sql = "select cdate,content from note where cdate = ?" //sql语句 //sql语句也需要转换成C的字符串 let cSql = sql.cString(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) var statement : OpaquePointer? = nil //statement指针对象 /*2、使用sqlite3_prepare_v2函数预处理SQL语句; @param1 db指针 @param2 要执行的sql语句 @param3 要传递sql语句的大小,传递所有 -1 @param4 statement指针对象 @param5 会告诉你那此没有被传递sql语句 */ if sqlite3_prepare_v2(db, cSql, -1, &statement, nil) == SQLITE_OK { //3、使用sqlite3_bind_text函数绑定参数;sql语句中的条件会用 ? 号来代替 let strDate = dateFormatter.string(from: model. Date as Date ) //把model.Date转为字符串 let cDate = strDate.cString(using: String.Encoding.utf8) //转换为C的字符串(char*) /* sqlite3_bind_text 绑定参数 @param1 statement指针对象 @param2 绑定参数的索引 1开始 @param3 正真要绑定的参数 @param4 要传递的最大字节数 @param5 回调函数 */ sqlite3_bind_text(statement, 1, cDate, -1, nil) //4、使用sqlite3_step函数执行SQL语句,遍历结果集; if sqlite3_step(statement) == SQLITE_ROW { //有记录返回 /*5、使用sqlite3_column_text等函数提取字段数据; @param1 statement指针对象 @param2 字段索引,比如 cdate==0,content==1 @return 返回提char * 需要 转为 String */ //char* -> String UnsafePointer相当于 char* let bufDate = sqlite3_column_text(statement, 0) //查询cdate let strDate = String(cString: bufDate!) //转为String self.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" //String->NSDate let date : NSDate = self.dateFormatter. date (from: strDate)! as NSDate let bufContent = sqlite3_column_text(statement, 1) //查询content let strContent = String(cString: bufContent!) //转为String // 6、使用sqlite3_finalize和sqlite3_close函数释放资源。 sqlite3_finalize(statement) //释放sql语句对象 sqlite3_close(db) let note = Note( date : date , content: strContent as NSString) //合为Note对象 return note } } } return nil } //查询所有数据方法 func findAll() -> NSMutableArray { let listData = NSMutableArray() //得到数据库的文件路径 let path:NSString = self.getDocumentPath() as NSString //将path:NSString转换为C的字符串(char*) let cpath = path.cString(using: String.Encoding.utf8.rawValue) /*1、sqlite3_open,打开数据库,如果数据库文件不存在则创建,存在则打开 @param1 文件路径, @param2 db指针类型 &db是传递db地址*/ if sqlite3_open(cpath, &db) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "数据库连接失败" ) } else { let sql = "select cdate,content from note" //sql语句 //sql语句也需要转换成C的字符串 let cSql = sql.cString(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) var statement : OpaquePointer? = nil //statement指针对象 /*2、使用sqlite3_prepare_v2函数预处理SQL语句; @param1 db指针 @param2 要执行的sql语句 @param3 要传递sql语句的大小,传递所有 -1 @param4 statement指针对象 @param5 会告诉你那此没有被传递sql语句 */ if sqlite3_prepare_v2(db, cSql, -1, &statement, nil) == SQLITE_OK { //3、使用sqlite3_bind_text函数绑定参数;sql语句中的条件会用 ? 号来代替 //4、使用sqlite3_step函数执行SQL语句,遍历结果集; while sqlite3_step(statement) == SQLITE_ROW { //有记录返回 /*5、使用sqlite3_column_text等函数提取字段数据; @param1 statement指针对象 @param2 字段索引,比如 cdate==0,content==1 @return 返回提char * 需要 转为 String */ let bufDate = sqlite3_column_text(statement, 0) //查询cdate let strDate = String(cString:bufDate!) //cString转为String self.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" //String->NSDate let date : NSDate = self.dateFormatter. date (from: strDate)! as NSDate let bufContent = sqlite3_column_text(statement, 1) //查询content let strContent = String(cString: bufContent!) //转为String let note = Note( date : date , content: strContent as NSString) //合为Note对象 listData.add(note) //添加到可变数组中 } } // 6、使用sqlite3_finalize和sqlite3_close函数释放资源。 sqlite3_finalize(statement) //释放sql语句对象 sqlite3_close(db) } return listData } //初始化 创建数据表 与 数据库文件 func plistCopyDocument() { //得到数据库的文件路径 let path:NSString = self.getDocumentPath() as NSString print (path) //将path:NSString转换为C的字符串(char*) let cpath = path.cString(using: String.Encoding.utf8.rawValue) /*sqlite3_open,打开数据库,如果数据库文件不存在则创建,存在则打开 @param1 文件路径, @param2 db指针类型 &db是传递db地址*/ if sqlite3_open(cpath, &db) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "数据库连接失败" ) } else { //sql语句:如果Note数据表不存在则创建,cdate 是主键,content为字符类型 let sql = "create table if not exists Note (cdate text primary key, content text)" //sql语句也需要转换成C的字符串 let cSql = sql.cString(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) /*sqlite3_exec执行sql,但sqlite3_exec没有返回结果集 @param1 指针, @param2 sql语句, @param3 回调函数, @param4 为回调函数传递参数的指针 @param5 errmsg错误信息*/ if sqlite3_exec(db, cSql, nil, nil, nil) != SQLITE_OK { sqlite3_close(db) //关闭链接 assert(false, "SQL语句执行失败" ) } else { sqlite3_close(db) //执行成功关闭链接 } } } //获取系统沙箱Document目录方法 func getDocumentPath() -> String { let documentDirectory: NSArray = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray let myDocPath = documentDirectory[0] as ! NSString //在myDocPath字符串的基础上累加另一个字符串NotesList.plist,目录+文件路径 let wtFile = myDocPath.appending(DB_FILE) as String return wtFile } } |