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];
Related
Here is my code i am getting only the last value of the database in the array but i need the entire column values in my array...
//select the values from the db
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM district_details"];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
char *field2 = (char *)sqlite3_column_text(statement, 1);
field2Str = [[NSString alloc]initWithUTF8String:field2];
str = [NSString stringWithFormat:#"%#", field2Str]; NSLog(#"the value from thr field1 from the district name is %#...",field2Str);
myarray =[[NSMutableArray alloc]initWithObjects:#"--select the value--",nil];
[myarray addObject:field2Str];
NSLog(#"the value of the myarray is......%#",myarray);
}
}
Initiate your array object once before you use it, if you initiate it inside while loop like you do it loses the previous added objects and takes fresh allocation inside the heap memory.
Just put this code inside viewDidLoad method and remove from while loop:
- (void)viewDidLoad {
[super viewDidLoad];
// mutable array allocation do once here
myarray =[[NSMutableArray alloc]initWithObjects:#"--select the value--",nil];
}
Now use below code to fetch entire column from data base:
//select the values from the db
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM district_details"];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
char *field2 = (char *)sqlite3_column_text(statement, 1);
field2Str = [[NSString alloc]initWithUTF8String:field2];
// --------- myarray allocation removed from here -----------
[myarray addObject:field2Str];
NSLog(#"the value of the myarray is......%#",myarray);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
The problem is that you are instantiating a new mutable array in ever loop of your while statement. You want to instantiate it once, before the loop, and inside the loop merely addObject.
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM district_details"];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK) {
myarray = [[NSMutableArray alloc] initWithObjects:#"--select the value--",nil];
while (sqlite3_step(statement)==SQLITE_ROW) {
char *field2 = (char *)sqlite3_column_text(statement, 1);
field2Str = [[NSString alloc] initWithUTF8String:field2];
[myarray addObject:field2Str];
}
sqlite3_finalize(statement); // remember to finalize to prevent SQLite leak
}
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];
}
Say I am having 1 table called ABC with fields ABCid,ABCname,ABCImagePath,ABCSequence. Now this table contains more than 40 rows inside the same.
Now I have an array of numbers say 1,4,5,7,8 and I want to compare these numbers with ABCid and fetch all the data from table ABC as per these IDs.
+ (void) getSelectedData : (int)ABCId
{
NSString *dbPath = [self getDBPath];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
NSString *query =[NSString stringWithFormat:#"select * from [ABC] where ABCId=%d",ABCId];
const char *sql = [query cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
{
[self getInitialDataToDisplay:dbPath];
ABC *DataObj = [[ABC alloc] initWithPrimaryKey:ABCId];
DataObj.ABCName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
ABCImagePath = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];
DataObj.ABCSequence = sqlite3_column_int(selectstmt,8);
[appDelegate.arrGetData addObject:DataObj]; }
else
{
NSAssert1(0,#"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
NSLog(#"%d",[appDelegate.DataArrayTrans count]);
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
But app gets crashed in the if condition. Also note that I use below lines from the pageController to call the above function from ABC Object file.
for(int i=0;i<[arrRId count];i++)
{
[ABC getSelectedData:[[arrRId objectAtIndex:i]integerValue]];
[arr576576 addObject:[appDelegate.arrGetData valueForKey:#"ABCId"]];
}
Please guide me where I am making mistake. Thank you.
your query should be like this select * from ABC where ABCId IN (1,4,5,7,8)
that's it.
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;
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;