iOS - object sent autorelease too many times - objective-c

I have a method that is reading some information from a sqlite db and initialising a class called Achievement. When I analyse this code I am given the feedback 'object sent autorelease too many times'. I don't really understand where I am going wrong - why is the retval object released on line 225 and not at the return statement on line 229?
Can someone please explain where I have made a mistake in the code below and how I can fix it?
Function Code (so answerer can easily copy/paste):
- (Achievement *)getAchievement:(int)Id
{
Achievement *retval = [[Achievement alloc] autorelease];
NSString *query = [NSString stringWithFormat:#"SELECT * FROM Achievements where ID = %d", Id];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
int Id = sqlite3_column_int(statement, 0);
char *name = (char *) sqlite3_column_text(statement, 1);
char *title = (char *) sqlite3_column_text(statement, 2);
char *description = (char *) sqlite3_column_text(statement, 3);
Boolean Achieved;
char *com = (char *) sqlite3_column_text(statement, 4);
NSString *c1 = [[[NSString alloc] initWithUTF8String:com] autorelease];
Achieved = [c1 isEqualToString:#"1"];
NSDate *CompletedDate = (NSDate *) sqlite3_column_text(statement, 5);
char *icon = (char *) sqlite3_column_text(statement, 6);
int New = sqlite3_column_int(statement, 7);
NSString *Title = [[[NSString alloc] initWithUTF8String:title] autorelease];
NSString *Description = [[[NSString alloc] initWithUTF8String:description] autorelease];
NSString *Name = [[[NSString alloc] initWithUTF8String:name] autorelease];
NSString *Icon = [[[NSString alloc] initWithUTF8String:icon] autorelease];
retval = [retval initDetails:Id :Name :Title: Description : Achieved : CompletedDate: Icon: New];
}
sqlite3_finalize(statement);
}
return retval;
}
Analysis feedback image:
As always any feedback is greatly appreciated.

Achievement *retval = [[Achievement alloc] autorelease];
this is very bad idea to do that. You ALWAYS have to initialize object before using it.
Instead you're initializing it in a loop:
retval = [retval initDetails:Id :Name :Title: Description : Achieved : CompletedDate: Icon: New];
I don't really get why you need to initialize the same object multiple times. Maybe, you need to create multiple objects and init them with different values?
Rearrange this:
Achievement *retval = nil;
while (...) {
[retval release];
retval = [[Achievement alloc] initDetails: ...];
}
return [retval autorelease];

I guess you're confusing the compiler with the wrong sequence of alloc, init, autorelease. What you should be doing instead is the following (pseudocode):
Achievement *retval = nil;
while (...) {
retval = [[[Achievement alloc] initDetails: ...] autorelease];
}
return retval;

Related

Getting NSDate from database and assign it to object NSDate

I am doing a project that will load data from database and display it in tableView.
I am wondering... What is the right code to be executed for NSDate from database to be assigned into voucher.date
line of code asked=(voucher.date = [[NSNumber alloc](init with sqlite3 statement line);)
Responses will be a great help ! :)
NSMutableArray *vouchers = [[NSMutableArray alloc]init];
while (sqlite3_step(statement) == SQLITE_ROW)
{
searchAndClaim *voucher = [[searchAndClaim alloc]init];
voucher.inquiry_id = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, 0)];
voucher.name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
voucher.date = [[NSNumber alloc](init with sqlite3 statement line);
voucher.branch = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 4)];
voucher.expDate = [[NSString alloc](init with sqlite3 statement line)];
[vouchers addObject:voucher];
}

query sqlite error out of memory xcode

I have an error. Problem with prepare statement: out of memory.
How to fix it?
Other queries are working normally. I do not know what can be.
Maybe this is a problem -(TelefonDetail *)telefonDetails:(int)iDMob ??
-(TelefonDetail *)telefonDetails:(int)iDMob
{
TelefonDetail *retvalTelefon = nil;
NSString *ZaprosTelefons = #"SELECT iDMob , marka, model,wifi, os, razmeri,Display,Camera,Stoimos,imageTel,opisCrat FROM MobTele WHERE iDMob=1";
sqlite3_stmt *statement1;
if (sqlite3_prepare_v2(_database, [ZaprosTelefons UTF8String], -1, &statement1, nil)
!= SQLITE_OK) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(_database));
}
else{ while (sqlite3_step(statement1) == SQLITE_ROW) {
int iDMob = sqlite3_column_int(statement1, 0);
char *Marka = (char *) sqlite3_column_text(statement1, 1);
char *Model = (char *) sqlite3_column_text(statement1, 2);
char *Wifi = (char *) sqlite3_column_text(statement1, 3);
char *OS = (char *) sqlite3_column_text(statement1, 4);
char *Razmeri = (char *) sqlite3_column_text(statement1, 5);
char *Display = (char *) sqlite3_column_text(statement1, 6);
char *Camera = (char *) sqlite3_column_text(statement1, 7);
char *Stoimos = (char *) sqlite3_column_text(statement1, 8);
Byte *imgTel = (Byte *) sqlite3_column_blob(statement1, 9);
NSString *marka = [[NSString alloc] initWithUTF8String:Marka];
NSString *model = [[NSString alloc] initWithUTF8String:Model];
NSString *wifi = [[NSString alloc] initWithUTF8String:Wifi];
NSString *os = [[NSString alloc] initWithUTF8String:OS];
NSString *razmeri = [[NSString alloc] initWithUTF8String:Razmeri];
NSString *display = [[NSString alloc] initWithUTF8String:Display];
NSString *camera = [[NSString alloc] initWithUTF8String:Camera];
NSString *Stoimost = [[NSString alloc] initWithUTF8String:Stoimos];
int len = sqlite3_column_bytes(statement1, 9);
NSData *imgData = [[NSData alloc] initWithBytes:imgTel length:len];
retvalTelefon = [[TelefonDetail alloc]initWhithIDMob:iDMob marka:marka model:model wifi:wifi os:os razmeri:razmeri display:display camera:camera Stoimost:Stoimost imegeTel:imgData];
}
sqlite3_finalize(statement1);
}
return retvalTelefon;
}
The "out of memory" error is often a misleading error message caused by trying to use a database without having opened it first (or if you accidentally set the sqlite3 database pointer to NULL). For example:
sqlite3 *db = NULL;
sqlite3_stmt *statement;
int rc;
// deliberately did not open database -- ERROR
// now try to use SQLite without opening database
if ((rc = sqlite3_prepare_v2(db, "select * from test", -1, &statement, NULL)) != SQLITE_OK)
NSLog(#"rc=%d errmsg=%s", rc, sqlite3_errmsg(db));
This will generate a return code (rc) of 21, SQLITE_MISUSE. And the error message is a misleading "out of memory":
2014-05-11 17:36:22.035 MyApp[19942:60b] rc=21 errmsg=out of memory

Cocoa sqlite db file

I'm having a bit of trouble understanding why the below code is not working:
sqlite3_stmt *statement5;
NSString *databasePath2 = #"default-gameData.db";
NSInteger speed_int = 0;
const char *dbPath2 = [databasePath2 UTF8String];
if(sqlite3_open(dbPath2, &db)==SQLITE_OK){
NSString *getspeeds = #"SELECT * FROM planeInfo";
NSLog(#"%#",getspeeds);
const char *getspeed_stmt = [getspeeds UTF8String];
if(sqlite3_prepare_v2(db, getspeed_stmt, -1, &statement5, nil)==SQLITE_OK){
NSLog(#"%d",sqlite3_step(statement5));
NSString *org_plane_info_id = [[NSString alloc] init];
while(sqlite3_step(statement5) == SQLITE_ROW){
if((const char*)sqlite3_column_text(statement5, 1)==NULL){
org_plane_info_id = #"no";
}
else{
org_plane_info_id = [[NSString alloc] initWithUTF8String:(const char*)sqlite3_column_text(statement5, 1)];
}
NSLog(#"%#",org_plane_info_id);
if(org_plane_info_id==plane_info_id){
NSString *speed = [[NSString alloc] initWithUTF8String:(const char*)sqlite3_column_text(statement5, 2)];
NSLog(#"%#",speed);
speed_int = [speed integerValue];
return speed_int;
}
}
}
}
if(speed_int==0){
return 0;
}
sqlite3_close(db);
I've found the source of the problem being the database path, the file is stored where the .h and .m files are so I think that's where I am going wrong, but what do I have to do to get that to work?
Cocoa/Foundation doesn't know where your file is. You need to tell it that it's in the app bundle.
NSString *databasePath2 = [[NSBundle mainBundle] pathForResource:#"default-gameData" ofType:#"db"];

How do I retrieve all the rows from an SQLite table?

hello guys i am doing some database operations in iphone .. please can anyone explain me how to retrieve all rows from the table..here in this example it retreives only the latest entered data..
while(sqlite3_step(statement) == SQLITE_ROW)
{
char *field1 = (char *) sqlite3_column_text(statement,0);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
char *field2 = (char *) sqlite3_column_text(statement,1);
NSString *field2Str = [[NSString alloc] initWithUTF8String: field2];
NSString *str = [[NSString alloc] initWithFormat:#"%#::%#",field1Str, field2Str];
textv.text=str;
[field1Str release];
[field2Str release];
}
You were doing all right so far. Just keep adding the final formatted string (str) in an NSMutableArray and finally return it from the function.
// Take an array to store all string.
NSMutableArray *allRows = [[[NSMutableArray alloc] init] autorelease];
while(sqlite3_step(statement) == SQLITE_ROW)
{
char *field1 = (char *) sqlite3_column_text(statement,0);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
char *field2 = (char *) sqlite3_column_text(statement,1);
NSString *field2Str = [[NSString alloc] initWithUTF8String: field2];
NSString *str = [NSString stringWithFormat:#"%#::%#",field1Str, field2Str];
// textv.text=str; // I don't know why your are mixing your view controller stuff's in database function.
// Add the string in the array.
allRows addObject:str];
[field1Str release];
[field2Str release];
}
// Finally you can return your allRows
return allRows;

Crashing application due to secondary thread trying to update UI

I am using a searchbar for selecting the records from table that is populated by Sqlite DB.
Upending the table in every 120 records and reloading the table in every 200 records.
My apps is crashing when i am dragging the table to a limit.When certain limit is covered Its crashing with error "secondary thread trying to update UI".here is the code
if (indexPath.row > limit)
{
llimit = llimit+200 ;
ulimit = ulimit+200 ;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[opq cancelAllOperations];
NSLog(#"before ns operation");
opq = [NSOperationQueue new];
NSInvocationOperation *op = [[[NSInvocationOperation alloc] initWithTarget:self selector:#selector(searchData) object:nil] autorelease];
[opq addOperation:op];
[pool drain];
i++;
limit = limit + 120 ;
}
- (void) searchData {
NSString *databaseName = #"imeating.sql";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDir=[documentPaths objectAtIndex:0];
NSString *databasePath=[documentsDir stringByAppendingPathComponent:databaseName];
sqlite3 *database;
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
// Setup the SQL Statement and compile it for faster access
sqlite3_stmt *compiledStatement ;
const char *sqlStatement ;
sqlStatement = "select category_id, upper(subitem_name), subitem_detail_id from subitem_detail where subitem_name LIKE ? order by subitem_name limit ?,?" ;
NSLog(#"inside search b4 wildsearch %#",searchString);
wildSearch = [NSString stringWithFormat:#"%#%#",searchString, #"%"];
if (sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(compiledStatement, 1, [wildSearch UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(compiledStatement, 2, llimit);
sqlite3_bind_int(compiledStatement, 3, ulimit);
if (llimit <200){
NSLog(#"with in if limit < 200");
itemArray = [[NSMutableArray alloc] init] ;
}
while (sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] ;
NSString *categoryId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *itemName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *itemId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
if (ulimit%200 == 0)
{
[newTableView reloadData];
}
[pool drain];
}
}
}
This is happening in device only not in simulator also Lazy loading is occurring in table view . I'm am using sqllite DB (contains huge amount of data) for populating the table.
I can drag the table to a certain range of limit after then application is crashing.Crashing limit is not constant.Please help me to implement this in perfect way
Thanks in advance
You can't update UI in a secondary thread, if you need to update UI then use -
[self performSelectorOnMainThread:#selector() withObject:nil waitUntilDone:YES];