Read second row in sqlite DB - ios

I finally figured out how to connect to my DB. I sucessfuly read the first row of my query, but how do I get the second row?
if (sqlite3_prepare_v2(localDB,query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *st0 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
NSString *st1 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
NSString *st2 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
NSString *st3 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
NSString *st4 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
NSString *st5 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];
NSLog(#"0: %#",st0);
NSLog(#"1: %#",st1);
NSLog(#"2: %#",st2);
NSLog(#"3: %#",st3);
NSLog(#"4: %#",st4);
NSLog(#"5: %#",st5);
}
else
{
NSLog(#"%s","Match not found");
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"%s","Error on SQLITE_OK");
}

Use while(sqlite3_step(statement) == SQLITE_ROW) instead of if (sqlite3_step(statement) == SQLITE_ROW), then you will be able to iterate through every row.

Related

How to display multiple rows and columns from database into tableView?

I'm trying to display rows and columns from database into tableview. My approach is: First I will get data from database and then I will assign SQL statements into variables like this:
- (NSMutableDictionary *)arrayOfInquiries
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = #"select * from inquiry_tb";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
Inquiry *voucher = [[Inquiry alloc]init];
NSNumber *id = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, 1)];
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 2)];
NSString *date = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 3)];
NSString *branch = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 4)];
NSMutableDictionary *inquiries = [NSMutableDictionary dictionaryWithObjectAndKeys:id,#"id",name,#"name",date,#"date",branch,#"branch",nil];
sqlite3_reset(statement);
return inquiries;
}
}
}
return nil;
}
And Im planning to return in to main view controller.
My question is: How can I return it to the main view controller. So that I can use it for the labels in the tableViewCell.
Is my approach right? Or is there much better approach?
#teach Yes you can do it.
Create NSMutableArray in your main view controller(.H).Suppose you have
NSMutableArray *id1,*name1,*date1,*branch1;
now you can add it in your sql variables like this
NSString *querySQL = #"select *yourcolumnnames from inquiry_tb where=?";
NSNumber *id = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, 0)];
[id1 addObject:id];
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
[name1 addObject:name];
NSString *date = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 2)];
[date1 addObject:date];
NSString *branch = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement,3 )];
[branch1 addObject:branch];
after that you can add your NSMutableArray *id1,*name1,*date1,*branch1; in your UITableViewcell and show the NSMutableArray.
Before the property has to assign(.H)
#property (strong, nonatomic) UILabel *id1label;
Now in (.m)
id1label=[[UILabel alloc]init];
id1label.frame=CGRectMake(115, 5, 400, 50);
id1label.font=[UIFont fontWithName: #"Neue Helvetica" size:14.0];
id1label.lineBreakMode = NSLineBreakByWordWrapping;
id1label.numberOfLines=0;
id1label.textColor=[UIColor blueColor];
NSArray *comment=[ youranotherNSMutableArray objectAtIndex:indexPath.section];
id1label.text=[comment objectAtIndex:indexPath.row];
[cell.contentView addSubview:id1label];

UITableView is not scrolling down

I created an ios app in which i have a table with dynamic cell generation. When i try to scroll down to the table. It returns to the top of the table. My code as follows:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(!self.customCell){
self.customCell = [self.tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
}
//Cell configuration
int quoteIndex = indexPath.row % [vendor count];
self.customCell.description.text = message[quoteIndex];
//Cell Layout
[self.customCell.description sizeToFit];
//Height of cell
float height = (CGRectGetMaxY(self.customCell.description.frame) +5);
return height + 1;
}
Here the cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_beaconDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:
#"SELECT vendor_name, enter_message, enter_image, vendor_image, received_date, time_interval FROM beacons WHERE id=%#", [unique objectAtIndex:indexPath.row]];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_beaconDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
title = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
description = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 1)];
NSString *fullImage = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 2)];
[fullImg insertObject:fullImage atIndex:indexPath.row];
NSString *vendorImage = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 3)];
[thumbnailImg insertObject:vendorImage atIndex:indexPath.row];
NSString *receivedDate = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 4)];
NSString *timeInterval = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)];
BeaconAdTime *beaconAdTime = [[BeaconAdTime alloc] init];
NSDate *updatedTime = [beaconAdTime updatedDateTime:receivedDate andInterval:[timeInterval intValue]];
int count = 0;
do
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat: #"MMM-dd hh:mm a"];
BeaconAdTime *beaconAdTime = [[BeaconAdTime alloc] init];
NSString *presentDateTime = [beaconAdTime presentDateTime];
NSDate *presentDateConvert = [dateFormatter dateFromString:presentDateTime];
count++;
if([updatedTime compare:presentDateConvert] == NSOrderedAscending || count == 1)
{
cell.title.text = title;
cell.description.text = description;
cell.receivedDate.text = receivedDate;
NSString *imgURL = fullImg[indexPath.row];
NSURL *imageURL = [NSURL URLWithString:imgURL];
UIImage *image = nil;
image = [UIImage imageWithData:[NSData dataWithContentsOfURL: imageURL]];
cell.vendorImage.image = image;
NSUserDefaults *userDefauts = [NSUserDefaults standardUserDefaults];
[userDefauts setObject:fullImg forKey:#"fullImage"];
[userDefauts synchronize];
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:localNotif];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:[NSString stringWithFormat:#"%d", indexPath.row]];
NSString *uid = [NSString stringWithFormat:#"%d", indexPath.row];
NSDictionary *infodict = [NSDictionary dictionaryWithObject:uid forKey:#"id"];
localNotif.userInfo = infodict;
NSDate *fireTime = [[NSDate date] addTimeInterval:0];
localNotif.fireDate = fireTime;
localNotif.alertBody = description;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
if(count>1)
{
break;
}
}
}
while (updatedTime!=nil);
}
sqlite3_finalize(statement);
}
sqlite3_close(_beaconDB);
}
// cell.title.text = vendor[indexPath.row];
//
// cell.vendorImage.image = [UIImage imageNamed:#"gg.jpg"];
return cell;
}
Thanks in advance.
You should not dequeue cells in height for row at index path. Also, self.customCell implies that you are working with just one cell. This is a very strange and unusual pattern.
Also, all those sqlite calls for each recycled cell is very inefficient. Instead, fetch the data you need into an array and work with that.
Also, avoid allocating formatters etc. in your cell method. Instead, use a static variable.

How to filter NSDictonary in UISearchBar?

In my app i am using UITableView To display List of items And UISearchBar to Filter the List Of items. All the data, i am reading it from sqlite3.
Following is my code:
below code is used to retrieve the data from Local DB and save the data into NSMutableDictionary called dict and the the dict is added into NSMutableArray
arr_AllTableData.
-(void)dataFromLocalDB
{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &PSATestDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM Test"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(PSATestDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
companyName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 9)];
[arr_Name addObject:companyName];
address = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 10)];
[arr_Address addObject:address];
number = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
[arr_TelephoneNo addObject:number];
url = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
[arr_WebAddress addObject:url];
_dict = [[NSMutableDictionary alloc] init];
[_dict setValue:arr_Name forKey:#"Name"];
[_dict setValue:arr_Address forKey:#"Address"];
[_dict setValue:arr_TelephoneNo forKey:#"Number"];
[_dict setValue:arr_WebAddress forKey:#"WebAddress"];
[arr_AllTableData addObject:_dict];
}
sqlite3_finalize(statement);
sqlite3_close(PSATestDB);
}
}
}
Following code is used to display data in UITableView
#pragma mark - UITableView Data source
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isFiltered == YES)
{
return [filtered_Name count];
}
else
{
return [arr_AllTableData count];
}
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"listCell";
PSAListCell *List = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (isFiltered == YES)
{
List.lbl_name.text = [filtered_Name objectAtIndex:indexPath.row];
}
else
{
List.lbl_name.text = [[_dict objectForKey:#"Name"] objectAtIndex:indexPath.row];
List.lbl_address.text = [[_dict objectForKey:#"Address"] objectAtIndex:indexPath.row];
List.lbl_ContactNO.text = [[_dict objectForKey:#"Number"] objectAtIndex:indexPath.row];
List.lbl_WebAddress.text = [[_dict objectForKey:#"WebAddress"] objectAtIndex:indexPath.row];
}
return List;
}
This is my UISearch Bar implemantion code:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if (searchText.length == 0)
{
// set our boolean flag
isFiltered = NO;
}
else
{
//set our boolean flag
isFiltered = YES;
// Alloc And init our filter NSMutable array
filtered_Name = [[NSMutableArray alloc]init];
//fast enumeration
NSMutableArray *test = [[NSMutableArray alloc]init];
for (NSDictionary *dictionary in arr_AllTableData)
{
NSArray *array = [dictionary objectForKey:#"Name"];
[test addObjectsFromArray:array];
}
for (NSString * name in test)
{
NSRange nameRang = [name rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (nameRang.location != NSNotFound)
{
[filtered_Name addObject:name];
}
}
}
[_ListTable reloadData];
}
I want to filter the NSDictionary which contains the data and want to display to the filter data on UITableView and if the data is not available in the dictionary then it need to call a web service?
Can anyone please help me out with this?
you can use NSPredicate to filter content from arr_AllTableData based upon your input string.
you can find filter array with predicate in below link.
http://alexeckermann.com/blog/legacy/filtering-nsarray-with-nspredicates

Changing NSString from previous UITableviewCell?

In my app I populate a NSMutableArray from a .sqlite database. Inside this array where I grab all the goodies from the database, I run a query to look inside the database. However, I want to be able to change this query dependent on what user selects in UITableview controller prior to this view controller. You'll see the query inside the function:
NSString *character = #"SELECT * FROM strengthexercises WHERE primarymuscle LIKE '%bicep%'";
const char *sql = [character cStringUsingEncoding:NSASCIIStringEncoding];
That lies within the array method:
-(NSMutableArray *) authorList{
_theauthors = [[NSMutableArray alloc] initWithCapacity:10];
#try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"StayhealthyExercises.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
{
NSLog(#"Cannot locate database file '%#'.", dbPath);
}
if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK))
{
NSLog(#"An error has occured: %s", sqlite3_errmsg(db));
}
NSString *character = #"SELECT * FROM strengthexercises WHERE primarymuscle LIKE '%bicep%'";
const char *sql = [character cStringUsingEncoding:NSASCIIStringEncoding];
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}else{
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
sqlColumns * author = [[sqlColumns alloc] init];
author.Name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
author.Muscle = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
author.Description = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
author.File= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
author.Sets= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
author.Reps= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 6)];
author.Equipment= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 7)];
author.PrimaryMuscle= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 8)];
author.SecondaryMuscle= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 9)];
author.Difficulty= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 10)];
[_theauthors addObject:author];
}
}
sqlite3_finalize(sqlStatement);
}
#catch (NSException *exception) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}
#finally {
sqlite3_close(db);
return _theauthors;
}
}
Now you should see my problem, the query is directly inside the array, I want to be able to control what the query is dependent on what the user selected in the UITableview controller before.
Table view delegate didSelectRowAtIndexPath triggers when user clicks on row in tableView
assuming you do have a tableView .
inside this function you can "query" what row was selected by switching indexPath.row
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = indexPath.row;
//lest examine the selected row
switch(row)
{
case 0:
{
//call function with string (for 0)
break;
}
case 1:
{
//call function with string (for 1)
break;
}
//etc..
}
}
also I assume you do have or can make this function that will lets say get integer and trigger the needed sql query.

How to add JSON data to a NSMutableArray?

Im trying to read rows from my SQLite DB and then convert the data to JSON and put it into an NSMutableArray. I then want to loop over the array and print the data into my table view.
This is what i do to load the data from SQLite:
entries = [[NSMutableArray alloc] init];
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM chatHistory GROUP BY channelID ORDER BY time DESC"];
sqlite3_stmt *statement;
if(sqlite3_prepare_v2([box db], [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
while(sqlite3_step(statement) == SQLITE_ROW) {
char *field1 = (char *) sqlite3_column_text(statement, 0);
NSString *channelID = [[NSString alloc] initWithUTF8String:field1];
char *field2 = (char *) sqlite3_column_text(statement, 0);
NSString *sender = [[NSString alloc] initWithUTF8String:field2];
char *field3 = (char *) sqlite3_column_text(statement, 0);
NSString *message = [[NSString alloc] initWithUTF8String:field3];
char *field4 = (char *) sqlite3_column_text(statement, 0);
NSString *recipient = [[NSString alloc] initWithUTF8String:field4];
char *field5 = (char *) sqlite3_column_text(statement, 0);
NSString *time = [[NSString alloc] initWithUTF8String:field5];
NSString *messageArray = [[NSString alloc] initWithFormat:#"[{ \"channelID\":\"%#\", \"sender\":\"%#\", \"message\":\"%#\", \"recipient\":\"%#\", \"time\":\"%#\"}]", channelID, sender, message, recipient, time];
// Convert to JSON object:
NSArray *jsonObject = [NSJSONSerialization JSONObjectWithData:[messageArray dataUsingEncoding:NSUTF8StringEncoding]
options:0 error:NULL];
[entries addObject:jsonObject];
Now here is how i try to add it to my table view:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ConvCell";
ConvCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ConvCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSArray *tableData = [self.entries valueForKey:#"message"];
NSLog(#"Message=%#", tableData);
cell.visitorName.text = (NSString *) [self.entries objectAtIndex:indexPath.row]; // This trows an error
cell.visitorAvatar.image = [UIImage imageNamed:#"hello.png"];
cell.messageTime.text = #"19.10";
return cell;
}
The error im getting is:
exception 'NSInvalidArgumentException', reason: '-[__NSCFArray length]: unrecognized selector sent to instance 0xa0cfc40'
Any ideas what I'm doing wrong?
Your use of JSON is interesting, it's just a short code way of creating dictionaries and nesting them in arrays. There are more containers than you really need and you could just create the dictionaries without all of the JSON wrangling.
That said, your actual error is because this line:
cell.visitorName.text = (NSString *) [self.entries objectAtIndex:indexPath.row];
should be
cell.visitorName.text = (NSString *) [tableData objectAtIndex:indexPath.row];
because you have those nested arrays are you aren't digging right to the bottom of them...
Your setup is not ideal. That being said...
You are casting your array of messages to a string.
[self.entries objectAtIndex:indexPath.row]
should return an array, not a string. What you want is something like this:
NSArray* jsonArray = [self.entries objectAtIndex:indexPath.row];
NSDictionary *dictionary = [jsonArray lastObject];
cell.visitorName.text = dictionary[#"sender"];
You can see that wrapping your one dictionary into an array does not really make any sense. Instead you could leave out the [...] in your JSON template. Then you would have
NSDictionary *dictionary = [self.entries objectAtIndex:indexPath.row];
BTW, the proper way to do this is to have a custom object Message with appropriate properties that you set right in your database fetch.

Resources