在Sqlite3数据库中存储自定义类对象失败

时间:2015-07-04 20:15:21

标签: ios objective-c mailcore2

我想将自定义类MCOIMAPSession对象存储到sqlite3数据库中。我阅读了NSKeyedArchiver并尝试使用下面的内容。

- (void) updateImapSessionForAccount :(NSString *) emailAddress :(MCOIMAPSession *)imapSession {

    const char *dbpath = [databasePath UTF8String];

    //SQLIte Statement
    NSString *selettablequery = [NSString stringWithFormat:@"select * from MailBoxInfoDBTable"];

    if (sqlite3_open(dbpath, &database) == SQLITE_OK)
    {

        //if(sqlite3_prepare_v2(database, [selettablequery UTF8String], -1, &statement, NULL) == SQLITE_OK)
        if (sqlite3_prepare(database, [selettablequery UTF8String], -1, &statement, NULL) ==SQLITE_OK)
        {
            // Take an array to store all string.
            //NSMutableArray *allRows = [[NSMutableArray alloc] init];

            while(sqlite3_step(statement) == SQLITE_ROW)
            {
                char *emailfield = (char *) sqlite3_column_text(statement,0);
                NSString *emailStr = [[NSString alloc] initWithUTF8String: emailfield];
                NSLog(@"updateMailMessagesPerAccount: %@", emailStr);

                if([emailStr isEqualToString:emailAddress])
                {
                    sqlite3_reset(statement);

                    NSData *messagesData = [NSKeyedArchiver archivedDataWithRootObject:imapSession];
                    NSString* stringFromData = [messagesData base64EncodedStringWithOptions:0];                        

                    NSString *sqlStr = [NSString stringWithFormat:@"update MailBoxInfoDBTable set imapsession='%@' where emailid='%@'", stringFromData, emailAddress];

                    const char *updateStatement = [sqlStr UTF8String];

                    if (sqlite3_prepare(database, updateStatement, -1, &statement, NULL) == SQLITE_OK)
                    {
                        if(SQLITE_DONE != sqlite3_step(statement))
                            NSLog(@"Error while updating. %s", sqlite3_errmsg(database));

                        sqlite3_finalize(statement);
                        sqlite3_close(database);

                        return;
                    }
                    else
                    {
                        NSLog(@"Error in statement: %s", sqlite3_errmsg(database));
                    }
                }
            }
        }
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }

}

- (MCOIMAPSession *) retrieveImapSessionForAccount :(NSString *) emailAddress {

    MCOIMAPSession *imapsessionObj = nil;

    const char *dbpath = [databasePath UTF8String];

    //SQLIte Statement
    NSString *selettablequery = [NSString stringWithFormat:@"select * from MailBoxInfoDBTable"];

    if (sqlite3_open(dbpath, &database) == SQLITE_OK)
    {
        //if(sqlite3_prepare_v2(database, [selettablequery UTF8String], -1, &statement, NULL) == SQLITE_OK)
        if (sqlite3_prepare(database, [selettablequery UTF8String], -1, &statement, NULL) ==SQLITE_OK)
        {
            // Take an array to store all string.
            //NSMutableArray *allRows = [[NSMutableArray alloc] init];

            while(sqlite3_step(statement) == SQLITE_ROW)
            {
                char *emailfield = (char *) sqlite3_column_text(statement, 0);
                NSString *emailStr = [[NSString alloc] initWithUTF8String: emailfield];
                NSLog(@"retrieveImapSessionForAccount: Email: %@", emailStr);

                if([emailStr isEqualToString:emailAddress])
                {
                    //const void *bytes = sqlite3_column_blob(statement, 3);
                    char *emailstring = (char *) sqlite3_column_text(statement, 3);
                    if (emailstring) {
                        NSString *messageStr = [[NSString alloc] initWithUTF8String: emailstring];
                        NSData *data = [[NSData alloc] initWithBase64EncodedString:messageStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
                        imapsessionObj = [NSKeyedUnarchiver unarchiveObjectWithData:data];
                    }
                }
            }
        }
        sqlite3_finalize(statement);
        sqlite3_close(database);
    }

    return imapsessionObj;
}

我在执行encodeWithCoder unrecognized selector sent to instance

时遇到了崩溃NSKeyedArchiver archivedDataWithRootObject:imapSession

然后,我在第三方类MCOIMAPSession.mm文件中添加了以下方法

- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self forKey:@"PROPERTY_KEY"];
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if(self = [super init]){
        self = [aDecoder decodeObjectForKey:@"PROPERTY_KEY"];
    }
    return self;
}

更新:我也试过了以下内容。

  @interface MCOIMAPSession : NSObject
    ....
  @end
  @interface NSObject (NSCoding)
     -(id)initWithCoder:(NSCoder*)decoder;
     -(void)encodeWithCoder:(NSCoder*)encoder;
  @end
  #endif

@implementation MCOIMAPSession
-(id)initWithCoder:(NSCoder *)decoder {
    if ((self=[super initWithCoder:decoder])) {
    }
    return self;
}
@end
@implementation NSObject (NSCoding)
-(id)initWithCoder:(NSCoder*)decoder {
    return [self init];
}
-(void)encodeWithCoder:(NSCoder*)encoder {}
@end

这里是MCOIMAPSESSION MCOIMAPSESSION link的文件..请让我知道我现在如何添加财产?

但是,我仍然看到同样的崩溃。当在sqlite数据库中存储自定义类MCOIMAPSession对象时,有人可以纠正我在这里做错了吗?

2 个答案:

答案 0 :(得分:2)

您对NSCoding方法的实施不正确。您不编码/解码self,您对self的每个属性/ ivar进行编码/解码。类似的东西:

- (void)encodeWithCoder:(NSCoder *)aCoder{
    // Replace the following with the class's actual properties
    [aCoder encodeObject:self.propertyA forKey:@"propertyA"];
    [aCoder encodeObject:self.propertyB forKey:@"propertyB"];
    [aCoder encodeObject:self.propertyC forKey:@"propertyC"];
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if(self = [super init]){
        // Replace the following with the class's actual properties
        _propertyA = [aDecoder decodeObjectForKey:@"propertyA"];
        _propertyB = [aDecoder decodeObjectForKey:@"propertyB"];
        _propertyC = [aDecoder decodeObjectForKey:@"propertyC"];
    }
    return self;
}

顺便说一下 - 你的问题与SQLite没什么关系。您的问题应该缩小到编码/解码的问题。

答案 1 :(得分:0)

您无法使用对象encodeWithCoder调用self。您必须编码(和解码)MCOIMAPSession的每个相关属性

修改

对于MCOIMAPSession,NSCoding方法应该看起来像

- (id)initWithCoder:(NSCoder *)decoder
{
  self = [super initWithCoder:decoder]
  if (self) {

    self.hostname = [decoder decodeObjectForKey:@"hostname"];
    self.port = [decoder decodeIntegerForKey:@"port"];
    self.username = [decoder decodeObjectForKey:@"username"];
    self.password = [decoder decodeObjectForKey:@"password"];
    // etc
  }
  return self;
}

-(void)encodeWithCoder:(NSCoder*)encoder
{
  [aCoder encodeObject:self.hostname forKey:@"hostname"];
  [aCoder encodeInteger:self.port forKey:@"port"];
  [aCoder encodeObject:self.username forKey:@"username"];
  [aCoder encodeObject:self.password forKey:@"password"];
  // etc
}

添加您需要的所有属性。并且请注意,表示其他自定义类的实例的属性也必须符合NSCoding。