Error while converting NSData to NSDictionary using NSKeyedUnarchiver - iphone

I want to archive and Unarchive data which contains NSDictionary object. Crash is observed while Unarchiving data. Please find the code and error below,
Archive:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:mydictobject];
Unarchiving:
NSData *Objdata = [[NSData alloc] initWithBytes:sqlite3_column_blob(statement, 2)
length:sqlite3_column_bytes(statement, 2)];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
initForReadingWithData:Objdata];
NSDictionary *dict = [NSDictionary dictionaryWithDictionary:
[NSKeyedUnarchiver unarchiveObjectWithData:Objdata]];
[dict objectForKey:#"key1"];
Error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0xfffffff8, 0xffffffc7, 0xf, 0x1, 0x2, 0x0, 0x0, 0x0)'
** First throw call stack:
(0x222b012 0x194e7e 0x222adeb 0xe78c90 0xe7f2 0x3c11 0x19256 0x43f8d5 0x43fb3d 0xe46e83 0x21ea376 0x21e9e06 0x21d1a82 0x21d0f44 0x21d0e1b 0x21857e3 0x2185668 0x39065c 0x2612 0x2545 0x1)
libc++abi.dylib: terminate called throwing an exception
Thanks.

// To read data do following
-(void) readAnimalsFromDatabase {
// Setup the database object
sqlite3 *database;
// Init the animals Array
dataArray = [[NSMutableArray alloc] init];
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "select * from anyTable";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aDescription = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aImageUrl = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:aName, #"name", aDescription, #"description", aImageUrl, #"imageURL", nil];
// Add the animal object to the animals Array
[dataArray addObject:dict];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
// Archive NSArray to NSData
NSData *archiveData = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
// UnArchive NSData to NSDictionary
NSArray *array = [NSArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:data]];
NSLog(#"%#",array);
}

Related

Potential Leak of an object

I am facing Potential leak of an object allocated. So how can I release my custom class object in loop . I am enclosing my code below herewith.
- (ProfileClass *) getUserProfile
{
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Profile"];
NSLog(#"query %#",query);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"MOFAdb.sqlite"];
ProfileClass *profile = nil;
// Open the database. The database was prepared outside the application.
if(sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
sqlite3_stmt *Statement1;
//int i=0;
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &Statement1, NULL) == SQLITE_OK) {
//int returnValue = sqlite3_prepare_v2(database, sql, -1, &Statement1, NULL);
if (sqlite3_step(Statement1) == SQLITE_ROW) {
// The second parameter indicates the column index into the result set.
NSString *userName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 0)];
NSString *userEmail = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 1)];
NSString *phoneNum = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 2)];
//int phone = sqlite3_column_int(Statement1, 2);
//NSLog(#"%d",phone);
//RecipeClass *rc = [[RecipeClass alloc] getRecipe:recipeName withRecipeIng:recipeIng withRecipeInst:recipeInstru withRecipeTips:recipeTips withRecipeDesc:recipeDesc];
if (profile)
[profile release];
profile = [[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum];
//NSLog(#"%#",fact);
//NSLog(#"%d",i);
//i++;
}
}
//Release the select statement memory.
sqlite3_finalize(Statement1);
//}
}
else {
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(database);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
}
return profile;
}
If I autorelease my profile = [[[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum] autorelease]; so my application crashes later. So I m release on if check but build and Analyze shows it as a warning.
You can also autorelease like that:
return [profile autorelease];
and retain the object of ProfileClass where you used it,
Ex- ProfileClass *objProfile=[[database getUserProfile] retain];
and release objProfile when you used it.
Your method: - (ProfileClass *) getUserProfile is not an instance method or a copy you should return an object that is autoreleased. But you should do it on the last line, since you have a if/else structure and if you only autorelease it on line profile = [[[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum] autorelease]; it will not get autoreleased if it fails the if statement and goes to else. So just do this:
return [profile autorelease];
Why don't you do:
return [profile autorelease];
And there is no need for the
if (profile)
check. Just release unconditionally. If profile is nil, it won't have any negative effect.
FWIW: I don't quite understand what your getProfile:etc... method does. I assume it is an initializer and nothing more (like the many initXYZ: methods in Cocoa). If so, you should probably call it initWithUserName:email:phone: to go with the convention. Could you post the method?
using an array you can solve this issue before calling this method
NSMutableArray *ProfileArray=[[NSMutableArray alloc] initWithArray:[ClassObj getUserProfile]];
ProfileClass *profileObj=[[ProfileArray objectAtIndex:0] retain];
[ProfileArray release];
// now you can use profile object anywhere... I hope memory issue is also solved
- (NSMutableArray *) getUserProfile
{
NSMutableArray *array=[[NSMutableArray alloc] init];
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Profile"];
NSLog(#"query %#",query);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"MOFAdb.sqlite"];
ProfileClass *profile = nil;
// Open the database. The database was prepared outside the application.
if(sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
sqlite3_stmt *Statement1;
//int i=0;
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &Statement1, NULL) == SQLITE_OK) {
//int returnValue = sqlite3_prepare_v2(database, sql, -1, &Statement1, NULL);
if (sqlite3_step(Statement1) == SQLITE_ROW) {
// The second parameter indicates the column index into the result set.
NSString *userName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 0)];
NSString *userEmail = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 1)];
NSString *phoneNum = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 2)];
//int phone = sqlite3_column_int(Statement1, 2);
//NSLog(#"%d",phone);
//RecipeClass *rc = [[RecipeClass alloc] getRecipe:recipeName withRecipeIng:recipeIng withRecipeInst:recipeInstru withRecipeTips:recipeTips withRecipeDesc:recipeDesc];
if (profile)
[profile release];
profile = [[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum];
[array addObject:profile];
[profile release];
}
}
//Release the select statement memory.
sqlite3_finalize(Statement1);
//}
}
else {
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(database);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
}
return [array autorelease];
}
I hope it will be helpful to you
cheers

Problem while scrolling Table View

I have the following problem while i scroll the table view:
NSCFString objectAtIndex:]: unrecognized selector sent to instance
I create NSDictionary tableContents and when i scroll it becomes deallocated.
This is my code:
- (void)viewDidLoad {
lessonsInGroup1 = [NSMutableArray array];
lessonsInGroup2 = [NSMutableArray array];
lessonsInGroup1 = [self grabRowsInGroup:#"1"];
lessonsInGroup2 = [self grabRowsInGroup:#"2"];
NSDictionary *temp =[[NSDictionary alloc]initWithObjectsAndKeys:lessonsInGroup1,#"General Information",lessonsInGroup2,#"LaTeX Examples", nil];
//[[tableContents alloc] init];
self.tableContents =temp;
[temp release];
NSLog(#"table %#",self.tableContents);
NSLog(#"table with Keys %#",[self.tableContents allKeys]);
self.sortedKeys =[[self.tableContents allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sorted %#",self.sortedKeys);
[lessonsInGroup1 release];
[lessonsInGroup2 release];
//[table reloadData];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
[super viewDidLoad];
}
- (NSMutableArray *) grabRowsInGroup:(NSString*)GroupID{
NSMutableArray *groupOfLessons;
groupOfLessons = [[NSMutableArray alloc] init];
char *sqlStatement;
int returnCode;
sqlite3_stmt *statement;
NSString *databaseName;
NSString *databasePath;
// Setup some globals
databaseName = #"TexDatabase.sql";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
// Setup the database object
sqlite3 *database;
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK) {
fprintf(stderr, "Error in opening the database. Error: %s",
sqlite3_errmsg(database));
sqlite3_close(database);
return;
}
sqlStatement = sqlite3_mprintf(
"SELECT * FROM Lessons WHERE LessonGroup = '%s';", [GroupID UTF8String]);
returnCode =
sqlite3_prepare_v2(database,
sqlStatement, strlen(sqlStatement),
&statement, NULL);
if(returnCode != SQLITE_OK) {
fprintf(stderr, "Error in preparation of query. Error: %s",
sqlite3_errmsg(database));
sqlite3_close(database);
return;
}
returnCode = sqlite3_step(statement);
while(returnCode == SQLITE_ROW) {
NSString *aLessonID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
NSString *aLessonGroup = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
NSString *aLessonTopic = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
NSString *aLessonText = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 3)];
NSString *aLessonCode = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 4)];
NSString *aLessonPicture = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 5)];
/*NSLog(aLessonID);
NSLog(aLessonGroup);
NSLog(aLessonTopic);
NSLog(aLessonText);
NSLog(aLessonCode);
NSLog(aLessonPicture);*/
// Create a new busCit object with the data from the database
Lesson *lesson = [[Lesson alloc] initWithLessonID:aLessonID LessonGroup:aLessonGroup LessonTopic:aLessonTopic LessonText:aLessonText LessonCode:aLessonCode LessonPicture:aLessonPicture];
[groupOfLessons addObject:lesson];
returnCode = sqlite3_step(statement);
}
sqlite3_finalize(statement);
sqlite3_free(sqlStatement);
return [groupOfLessons autorelease];
}
What does your #property for tableofContents look like?
Also, you are going to run into issues with
[lessonsInGroup1 release];
[lessonsInGroup2 release];
because you are autoreleasing those in the grabRowsInGroup:
So, you don't need to call release them.
Looks like you are calling objectAtIndex on NSString. It should rather be some array

Problem With Sqlite Data Retrieving

I have an SQLite database, and when I am trying to get the data from the database, I get the last inserted element repeatedly. How can I get all the elements with no repetition.
The code I've written:
- (NSMutableArray *) gettingData {
sqlDict = [[NSMutableDictionary alloc] init];
membersInfoArray =[[NSMutableArray alloc]init ];
[self checkAndCreateDatabase];
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
const char *sql = "select * from ProductList";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
{
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{
NSString *prdbcode = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
[sqlDict setObject:prdbcode forKey:#"Barcode"];
[prdbcode release];
NSString *prdname = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
[sqlDict setObject:prdname forKey:#"ProductName"];
[prdname release];
NSString *prdDesc = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];
[sqlDict setObject:prdDesc forKey:#"ProductDescription"];
[prdDesc release];
NSString *prdstatus = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)];
[sqlDict setObject:prdstatus forKey:#"ProductStatus"];
[prdstatus release];
[membersInfoArray addObject:sqlDict];
[sqlDict release];
}
}
sqlite3_finalize(selectstmt);
}
sqlite3_close(database);
return membersInfoArray;
}
I am retrieving the data as follows:
NSMutableArray *sqlArray = [sqlViewController gettingData];
Thank you.
Just Declare your array globally instead of declare locally in your method. Your problem will resolved.

SQLite insert error in iOS

I'm trying to do an insert statement with SQLite and I'm sure I must be doing something stupid, but I can't figure out how to get it to work.
The error I'm getting is: "Error preparing statement"
Here's my code:
NSString *json_string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
// Create new SBJSON parser object
SBJsonParser *parser = [[SBJsonParser alloc] init];
// parse the JSON response into an object
NSDictionary *download = [parser objectWithString:json_string error:nil];
NSDictionary *buildings = [download objectForKey:#"buildings"];
// Open DB
sqlite3 *db = [RLSampleAppDelegate getNewDBConnection];
// Buildings
for (NSDictionary *building in buildings)
{
NSDictionary *thisbuilding = [building objectForKey:#"building"];
NSLog(#"%#", [thisbuilding objectForKey:#"buildingname"]);
sqlite3_stmt *statement = nil;
NSString* someString = [NSString stringWithFormat:#"INSERT INTO building (buildingid, buildingname) VALUES (\'%#\', \'%#\')", [thisbuilding objectForKey:#"buildingid"], [thisbuilding objectForKey:#"buildingname"]];
NSLog(#"somestring: %#", someString);
const char *sql = (const char *) someString;
if(sqlite3_prepare_v2(db, sql, -1, &statement, NULL)!=SQLITE_OK)
NSAssert1(0,#"Error preparing statement",sqlite3_errmsg(db));
while(sqlite3_step(statement) == SQLITE_DONE){}
sqlite3_finalize(statement);
}
[json_string release];
You can't use a NSString instance in the SQLite3 API. You need a pure C string.
So, try changing this:
const char *sql = (const char *) someString;
Into:
const char *sql = [someString cStringUsingEncoding:[NSString defaultCStringEncoding]];
Try this:
sqlite3_prepare_v2(db, [someString UTF8String], -1, &statement, nil)
First you need sure that you get database file from Document or Library folder of simulator. Because you can not insert databases stored in the app resources. And try my code.
NSString *json_string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
// Create new SBJSON parser object
SBJsonParser *parser = [[SBJsonParser alloc] init];
// parse the JSON response into an object
NSDictionary *download = [parser objectWithString:json_string error:nil];
NSDictionary *buildings = [download objectForKey:#"buildings"];
// Open DB
sqlite3 *db = [RLSampleAppDelegate getNewDBConnection];
// Buildings
for (NSDictionary *building in buildings)
{
NSDictionary *thisbuilding = [building objectForKey:#"building"];
NSLog(#"%#", [thisbuilding objectForKey:#"buildingname"]);
NSString* someString = [NSString stringWithFormat:#"INSERT INTO building (buildingid, buildingname) VALUES ('%#','%#')", [thisbuilding objectForKey:#"buildingid"], [thisbuilding objectForKey:#"buildingname"]];
const char *sql = [someString UTF8String];
char *error;
if (sqlite3_exec(db, sql, NULL, NULL, &error)==SQLITE_OK) {
NSLog(#"insert success.");
}
}
[json_string release];

i cant Load value into array

const char *dbpath = [databasePath UTF8String];
UserArray = [[NSMutableArray alloc]init];
sqlite3_stmt *compiledStatement;
if(sqlite3_open(dbpath, &db) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"select UserName,FullName,Email from User" ];
const char *sqlStatement =[querySQL UTF8String];
if(sqlite3_prepare_v2(db ,sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement) == SQLITE_ROW )
{
NSString *aUserName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *aFullName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aEmail = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
// Create a new animal object with the data from the database
User *obj_user = [[User alloc] initWithUserName:aUserName FullName:aFullName Email:aEmail];
// Add the animal object to the animals Array
[UserArray addObject:obj_user];
[User release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(db);
}
Hey All,
I am trying to put value into array of object but it throw's error Like Below...
anyone guide me why i got this type of error.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UICachedDeviceRGBColor UserArray]: unrecognized selector sent to instance 0x6a396f0'