欢迎访问 水平网    今天是:2018年06月22日 注册 | 登录 | 订阅 | 收藏
>> 苹果【Apple】 >> 编程应用 >> IOS 对象归档 数据库存储
推荐文章
热点文章

IOS 对象归档 数据库存储

作者:未知,  来源:网络,  阅读:853,  发布时间:2014-05-06  【放入收藏夹

在IOS开发中遇到数据库保存很正常。

但是要保存的对象中如果不全是基本数据类型,或者不是数据库是支持的类型,是不是瞬间石化了。

例如:

在一个Message对象中包含一个Attatchment对象,现在要求是每个Message要保存起来,选择sqlite数据库保存是不是很正常(反正我是用的他),但是sqlite中并不支持Attatchment类型,怎么搞???

法一:

把Attatchment中的所有属性放到Message中,没有问题,也是一个很好的办法,但是这样是不是有点牵强呢?

法二:

也是本人今天要介绍的方法,就是对象归档成NSData后在存储。查询出来的时候在解档一下就OK了。

废话少说,直接给出代码(数据库存储用到了第三方库FMDB):

 

源码下载地址

 

给出Attatchment实体类(只是做一个简单的测试就不给出详细定义了):

//
// Attatchment.h
// Demo
//

#import <Foundation/Foundation.h>

@interface Attatchment : NSObject <NSCoding>{
NSString *_localPath;
}
@property (nonatomic , copy) NSString *localPath;
@end

//
// Attatchment.m
// Demo
//

#import "Attatchment.h"

@implementation Attatchment
@synthesize localPath = _localPath;
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_localPath forKey:@"localPath"];
}

- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if(self != nil){
_localPath = [[aDecoder decodeObjectForKey:@"localPath"] retain];
}
return self;
}
@end

 

在给出Message实体(也是一个简单的定义):

//
// Message.h
// Demo
//

#import <Foundation/Foundation.h>
#import "Attatchment.h"

@interface Message : NSObject{
NSString *_messageId;
Attatchment *_att;
}
@property (nonatomic , copy) NSString *messageId;
@property (nonatomic , retain) Attatchment *att;
@end

 

//
// Message.m
// Demo
//

#import "Message.h"

@implementation Message
@synthesize messageId = _messageId;
@synthesize att = _att;
@end

这样两个实体就定义完了。

 

重要的过程就是存储了:

这里给出了自己写的一个DBManager(写的粗糙,见谅!)

//
// DBManager.h
// FetionHD
//


#import <Foundation/Foundation.h>
#import "FMDatabase.h"
#import "Message.h"

#define dataBasePath [[(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)) lastObject]stringByAppendingPathComponent:dataBaseName]
#define dataBaseName @"dataBase.sqlite"

@interface DBManager : NSObject

/****/
/**
* @brief 数据库对象单例方法
*
* @return 返回FMDateBase数据库操作对象
*/
+ (FMDatabase *)createDataBase;


/**
* @brief 关闭数据库
*/
+ (void)closeDataBase;

/**
* @brief 清空数据库内容
*/
+ (void)deleteDataBase;

/**
* @brief 判断表是否存在
*
* @param tableName 表明
*
* @return 创建是否成功
*/
+ (BOOL) isTableExist:(NSString *)tableName;


/**
* @brief 创建所有表
*
* @return
*/
+ (BOOL)createTable;
/**
* @brief 添加chatdata 如果主键重复就更新
*
* @param chatData 要保存的chatdata
*
* @return 返回是否保存或者更新成功
*/
+ (BOOL) saveOrUpdataMessage:(Message*)chatData;
+ (Message *) selectMessageByMessageId:(NSString*)messageId;
@end

//
// DBManager.m
// FetionHD


#import <Foundation/Foundation.h>
#import "DBManager.h"

#define debugMethod(...) NSLog((@"In %s,%s [Line %d] "), __PRETTY_FUNCTION__,__FILE__,__LINE__,##__VA_ARGS__)
static FMDatabase *shareDataBase = nil;
@implementation DBManager

/**
创建数据库类的单例对象

**/
//+ (FMDatabase *)createDataBase {
// //debugMethod();
// @synchronized (self) {
// if (shareDataBase == nil) {
//
// shareDataBase = [[FMDatabase databaseWithPath:dataBasePath] retain];
// }
// return shareDataBase;
// }
//}
//这种方法可以达到线程安全,但多次调用时会导致性能显著下降



+ (FMDatabase *)createDataBase {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shareDataBase = [[FMDatabase databaseWithPath:dataBasePath] retain];
});
return shareDataBase;
}

/**
判断数据库中表是否存在
**/
+ (BOOL) isTableExist:(NSString *)tableName
{
FMResultSet *rs = [shareDataBase executeQuery:@"select count(*) as 'count' from sqlite_master where type ='table' and name = ?", tableName];
while ([rs next])
{
// just print out what we've got in a number of formats.
NSInteger count = [rs intForColumn:@"count"];
NSLog(@"%@ isOK %d", tableName,count);

if (0 == count)
{
return NO;
}
else
{
return YES;
}
}

return NO;
}

/**
创建表
**/
+ (BOOL)createTable {
debugMethod();
NSLog(@"%@",dataBasePath);
if (1){
{
shareDataBase = [DBManager createDataBase];
if ([shareDataBase open]) {
if (![DBManager isTableExist:@"message_table"]) {
NSString *sql = @"CREATE TABLE \"message_table\" (\"message_id\" TEXT PRIMARY KEY NOT NULL check(typeof(\"message_id\") = 'text') , \"att\" BLOB)";
NSLog(@"no Medicine ");
[shareDataBase executeUpdate:sql];
}
[shareDataBase close];
}
}
}
return YES;
}

/**
关闭数据库
**/
+ (void)closeDataBase {
if(![shareDataBase close]) {
NSLog(@"数据库关闭异常,请检查");
return;
}
}

/**
删除数据库
**/
+ (void)deleteDataBase {
if (shareDataBase != nil) {
//这里进行数据库表的删除工作
}
}

+ (BOOL) saveOrUpdataMessage:(Message*)message
{
BOOL isOk = NO;
shareDataBase = [DBManager createDataBase];
if ([shareDataBase open]) {
isOk = [shareDataBase executeUpdate:
@"INSERT INTO \"message_table\" (\"message_id\",\"att\") VALUES(?,?)",message.messageId,[NSKeyedArchiver archivedDataWithRootObject:message.att]];
[shareDataBase close];
}
return isOk;
}

+ (Message *) selectMessageByMessageId:(NSString*)messageId
{
Message *m = nil;
shareDataBase = [DBManager createDataBase];
if ([shareDataBase open]) {
FMResultSet *s = [shareDataBase executeQuery:[NSString stringWithFormat:@"SELECT * FROM \"message_table\" WHERE \"message_id\" = '%@'",messageId]];
if ([s next]) {
m = [[Message alloc] init];
m.messageId = [s stringForColumn:@"message_id"];
m.att = [NSKeyedUnarchiver unarchiveObjectWithData:[s dataForColumn:@"att"]];
}
[shareDataBase close];
}
return m;
}
@end

剩下的工作就是搞个界面调用一下@_@

- (IBAction)addAction:(id)sender{
Message *message = [[Message alloc] init];
Attatchment *att = [[Attatchment alloc] init];
message.messageId = @"11";
message.att = att;
att.localPath = @"a.png";
[DBManager createTable];
[DBManager saveOrUpdataMessage:message];

[att release];

[message release];

 

}

- (IBAction)selectAction:(id)sender{
Message *message = [DBManager selectMessageByMessageId:@"11"];
NSLog(@"%@",message.att.localPath);
NSLog(@"%@",message.messageId);
}

记得在工程中添加FMDB库和sqlite3库,跑一下试试会有想不到的效果哦。

TGAS:IOS对象归档数据库
评论【共有0条评论】查看所有评论
昵称:(*)   邮箱:   QQ:   验证码: 看不清楚?点击刷新验证码