IOS 對象歸檔 資料庫儲存

來源:互聯網
上載者:User

在IOS開發中遇到資料庫儲存很正常。

但是要儲存的對象中如果不全是基礎資料型別 (Elementary Data Type),或者不是資料庫是支援的類型,是不是瞬間石化了。

例如:

在一個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庫,跑一下試試會有想不到的效果哦。

這是本人的第一篇博文,歡迎吐槽@_@。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.