交友:微信号 dwjluck2013
一、封装FMDB单例
(1)JLFMDBHelp.h文件
1 #import <Foundation/Foundation.h> 2 #import <FMDatabase.h> 3 4 @interface JLFMDBHelp : NSObject 5 6 @property(nonatomic,strong)NSString *fileName;//数据库名 7 8 @property(nonatomic,strong)FMDatabase *database; //数据库对象 9 10 + (JLFMDBHelp*)sharedFMDBHelp; 11 //数据库存储路径 12 - (NSString*)dbPath; 13 //打开数据库 14 - (void)openDB; 15 //关闭数据库 16 - (void)closeDB; 17 //创建表 18 - (void)dbCreateTable; 19 //插入 20 -(BOOL)insertDBWithData:(NSData *)newsData dbWithString:(NSString *)channelWithStr; 21 //查询 22 -(NSMutableArray *)selectDBWithChannel:(NSString *)channel; 23 //给数据库命名 24 - (void)createDBWithName:(NSString*)dbName; 25 26 //无返回结果集的操作 27 - (BOOL)notResultSetWithSql:(NSString*)sql; 28 //查询操作 29 - (NSArray*)qureyWithSql:(NSString*)sql; 30 @end
(2)JLFMDBHelp.m文件
1 #import "JLFMDBHelp.h" 2 #import "JLMainViewsModel.h" 3 4 @interface JLFMDBHelp() 5 6 @end 7 8 @implementation JLFMDBHelp 9 10 + (JLFMDBHelp*)sharedFMDBHelp { 11 static JLFMDBHelp *help = nil; 12 static dispatch_once_t onceToken; 13 dispatch_once(&onceToken, ^{ 14 help = [[JLFMDBHelp alloc] init]; 15 }); 16 return help; 17 } 18 19 #pragma amrk - 根据名称创建沙盒路径用来保存数据库文件 20 - (NSString*)dbPath { 21 //说明fileName不为空 22 if (self.fileName.length) { 23 //1.创建DB,路径 24 NSString *documents = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 25 NSString *filePath = [documents stringByAppendingPathComponent:@"channelNews.db"]; 26 return filePath; 27 } else { 28 return @""; 29 } 30 } 31 32 #pragma mark - 让用户来命名数据库的名称 33 - (void)createDBWithName:(NSString*)dbName { 34 if (dbName.length == 0) { 35 //是防止用户直接传值为nil 或者 NULL 36 self.fileName = @""; 37 }else{ 38 self.fileName = [dbName stringByAppendingString:@".db"]; 39 } 40 } 41 42 #pragma mark - 创建数据库对象 43 //懒加载 44 - (FMDatabase*)database { 45 if (!_database) { 46 _database = [FMDatabase databaseWithPath:[self dbPath]]; 47 } 48 return _database; 49 } 50 #pragma mark - 判断是否存在表 51 - (BOOL) isTableOK:(NSString *)tableName 52 { 53 NSString *sqlStr = [NSString stringWithFormat:@"select count(*) as 'count' from sqlite_master where type ='table' and tbl_name = '%@';",tableName]; 54 FMResultSet *rs = [self.database executeQuery:sqlStr]; 55 while ([rs next]) 56 { 57 NSInteger count = [rs intForColumn:@"count"]; 58 NSLog(@"isTableOK %ld", (long)count); 59 60 if (0 == count) 61 { 62 return NO; 63 } 64 else 65 { 66 return YES; 67 } 68 } 69 return NO; 70 } 71 #pragma mark - 创建数据库表 72 - (void)dbCreateTable { 73 if([self.database open]){ 74 if (![self isTableOK:@"t_newsWithChannel"]) { 75 NSString *sql = @"create table if not exists t_newsWithChannel (newsID integer primary key autoincrement,nwesName blob,newsType VARCHAR not null);"; 76 BOOL execResult = [self.database executeUpdate:sql]; 77 if(execResult){ 78 NSLog(@"table ok"); 79 }else{ 80 NSLog(@"table fail"); 81 } 82 } 83 [self closeDB]; 84 }else{ 85 NSLog(@"open fail"); 86 } 87 } 88 89 #pragma mark - 打开数据库的方法 90 - (void)openDB { 91 BOOL isOpen = [self.database open]; 92 if (isOpen) { 93 NSLog(@"打开数据库成功"); 94 } else { 95 NSLog(@"打开数据库失败"); 96 } 97 } 98 99 #pragma mark - 关闭数据库的方法 100 - (void)closeDB { 101 BOOL isClose = [self.database close]; 102 if (isClose) { 103 NSLog(@"关闭数据库成功"); 104 } else { 105 NSLog(@"关闭数据库失败"); 106 } 107 } 108 //插入 109 -(BOOL)insertDBWithData:(NSData *)newsData dbWithString:(NSString *)channelWithStr{ 110 [self.database open]; 111 NSString *sql = [NSString stringWithFormat:@"insert into t_newsWithChannel (nwesName,newsType) values (?,?)"]; 112 BOOL execResult = [self.database executeUpdate:sql,newsData,channelWithStr]; 113 if(execResult){ 114 NSLog(@"insert ok"); 115 return YES; 116 }else{ 117 NSLog(@"insert fail"); 118 return NO; 119 } 120 } 121 //查询 122 -(NSMutableArray *)selectDBWithChannel:(NSString *)channel{ 123 NSString *resultSql = [NSString stringWithFormat:@"select * from t_newsWithChannel where newsType = '%@'",channel]; 124 FMResultSet *set = [self.database executeQuery:resultSql]; 125 NSMutableArray *array = [NSMutableArray array]; 126 while ([set next]) { 127 NSData *newsData = [set dataForColumn:@"nwesName"]; 128 JLMainViewsModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:newsData]; 129 if (model) { 130 [array addObject:model]; 131 } 132 } 133 return array; 134 } 135 @end
二、模型数据
(1)JLMainViewsModel.h文件
要遵守协议
@interface JLMainViewsModel : NSObject<NSCopying,NSCoding>
(2)JLMainViewsModel.m文件
1 -(void)encodeWithCoder:(NSCoder *)aCoder{ 2 3 [aCoder encodeObject:self.fromSource forKey:@"fromSource"]; 4 [aCoder encodeObject:self.url forKey:@"url"]; 5 [aCoder encodeObject:self.title forKey:@"title"]; 6 [aCoder encodeObject:self.type forKey:@"type"]; 7 [aCoder encodeObject:self.newsTime forKey:@"newsTime"]; 8 [aCoder encodeObject:self.imageUrl forKey:@"imageUrl"]; 9 [aCoder encodeObject:self.imageArray forKey:@"imageArray"]; 10 [aCoder encodeObject:self.bigImageUrl forKey:@"bigImageUrl"]; 11 [aCoder encodeObject:self.bigImageArray forKey:@"bigImageArray"]; 12 [aCoder encodeObject:self.recommend forKey:@"recommend"]; 13 [aCoder encodeObject:self.exData forKey:@"exData"]; 14 [aCoder encodeObject:self.newsType forKey:@"newsType"]; 15 [aCoder encodeObject:self.style forKey:@"style"]; 16 [aCoder encodeObject:self.gzh forKey:@"gzh"]; 17 [aCoder encodeObject:self.uniqId forKey:@"uniqId"]; 18 [aCoder encodeObject:self.subdesc forKey:@"subdesc"]; 19 [aCoder encodeObject:self.autoplay forKey:@"autoplay"]; 20 [aCoder encodeObject:self.fromicon forKey:@"fromicon"]; 21 [aCoder encodeObject:self.webUrl forKey:@"webUrl"]; 22 } 23 24 -(id)initWithCoder:(NSCoder *)aDecoder{ 25 if (self = [super init]) { 26 self.fromSource = [aDecoder decodeObjectForKey:@"fromSource"]; 27 self.url = [aDecoder decodeObjectForKey:@"url"]; 28 self.title = [aDecoder decodeObjectForKey:@"title"]; 29 self.type = [aDecoder decodeObjectForKey:@"type"]; 30 self.newsTime = [aDecoder decodeObjectForKey:@"newsTime"]; 31 self.imageUrl = [aDecoder decodeObjectForKey:@"imageUrl"]; 32 self.imageArray = [aDecoder decodeObjectForKey:@"imageArray"]; 33 self.bigImageUrl = [aDecoder decodeObjectForKey:@"bigImageUrl"]; 34 self.bigImageArray = [aDecoder decodeObjectForKey:@"bigImageArray"]; 35 self.recommend = [aDecoder decodeObjectForKey:@"recommend"]; 36 self.exData = [aDecoder decodeObjectForKey:@"exData"]; 37 self.newsType = [aDecoder decodeObjectForKey:@"newsType"]; 38 self.style = [aDecoder decodeObjectForKey:@"style"]; 39 self.gzh = [aDecoder decodeObjectForKey:@"gzh"]; 40 self.uniqId = [aDecoder decodeObjectForKey:@"uniqId"]; 41 self.subdesc = [aDecoder decodeObjectForKey:@"subdesc"]; 42 self.autoplay = [aDecoder decodeObjectForKey:@"autoplay"]; 43 self.fromicon = [aDecoder decodeObjectForKey:@"fromicon"]; 44 self.webUrl = [aDecoder decodeObjectForKey:@"webUrl"]; 45 } 46 return self; 47 } 48 49 - (id)copyWithZone:(NSZone *)zone 50 { 51 JLMainViewsModel *model = [[[self class] allocWithZone:zone]init]; 52 return model; 53 }
三、存储数据 在网络请求成功后存储 只是存储时的代码
1 //网络请求回调 成功 2 if(successBlock){ 3 JLFMDBHelp *fmdbHelp = [JLFMDBHelp sharedFMDBHelp]; 4 //数据库名 5 [fmdbHelp createDBWithName:@"t_newsWithChannel"]; 6 //路径 7 NSString *filePath = [fmdbHelp dbPath]; 8 //创建数据库表 9 [fmdbHelp dbCreateTable]; 10 11 FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:filePath]; 12 [queue inDatabase:^(FMDatabase *db) { 13 [mArray enumerateObjectsUsingBlock:^(JLMainViewsModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 14 //将数组转换成字符串 15 NSData *newsData = [NSKeyedArchiver archivedDataWithRootObject:obj]; 16 //插入 17 if ([fmdbHelp insertDBWithData:newsData dbWithString:chanl]) { 18 [fmdbHelp closeDB]; 19 }else{ 20 [fmdbHelp closeDB]; 21 } 22 }]; 23 }]; 24 25 26 // //1.获取存储的路径 27 // NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 28 // NSString *filePatha = [documents stringByAppendingPathComponent:@"newsModelWithArray.plist"]; 29 // //归档 30 // [NSKeyedArchiver archiveRootObject:mArray toFile:filePatha]; 31 // NSLog(@"路径-----%@",filePath); 32 successBlock(mArray.copy); 33 }
四、在需要用的vc中读取数据
1 #pragma mark - 本地数据库中读取数据(模型对象) 2 -(void)getdbDataSource{ 3 JLFMDBHelp *fmdbHelp = [JLFMDBHelp sharedFMDBHelp]; 4 //数据库名 5 [fmdbHelp createDBWithName:@"channelNews"]; 6 //打开数据库 7 [fmdbHelp openDB]; 8 9 NSMutableArray *mNewsArray = [fmdbHelp selectDBWithChannel:self.newsType]; 10 NSLog(@"%@",mNewsArray); 11 }
重点:遇到的坑,存储数据的时候
NSString *sql = [NSString stringWithFormat:@"insert into t_newsWithChannel (nwesName,newsType) values (?,?)"];
values (?,?) 这里一定要用占位符,不能用values (%@,%@) 否则存储看不出问题,存储的数据却不对,反序列化的时候不会走model中的
-(id)initWithCoder:(NSCoder *)aDecoder方法