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];
Related
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.
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.
I am creating an iPhone app. In that I am displaying some content in a table cell. Now, I want to display the full-size image when click on the table cell.
I used the following code. But I don't know how to display the image in full screen when I select the table cell.
And also I want to get back when I tap on background when the image is in full screen.
-(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, 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)];
fullImg = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 2)];
NSString *receivedDate = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 3)];
NSString *timeInterval = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
BeaconAdTime *beaconAdTime = [[BeaconAdTime alloc] init];
NSDate *updatedTime = [beaconAdTime updatedDateTime:receivedDate andInterval:[timeInterval intValue]];
while (updatedTime!=nil)
{
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];
if(updatedTime <= presentDateConvert)
{
// [message insertObject:description atIndex:indexPath.row];
// [vendor insertObject:title atIndex:indexPath.row];
cell.title.text = title;
cell.description.text = description;
cell.receivedDate.text = receivedDate;
break;
}
}
}
sqlite3_finalize(statement);
}
sqlite3_close(_beaconDB);
}
cell.title.text = vendor[indexPath.row];
cell.vendorImage.image = [UIImage imageNamed:#"gg.jpg"];
// cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:thumbnailImg]]];
return cell;
}
something like that:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = tableView.visibleCells[indexPath.row];
UIViewController *imageVC = [UIViewController new];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
imageVC.view.frame = CGRectMake(0, 0, screenWidth, screenHeight);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageVC.view.frame];
imageView.image = cell.imageView.image;
imageView.userInteractionEnabled=YES;
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTouched:)];
[imageView addGestureRecognizer:tapGR];
[self presentViewController:imageVC animated:YES completion:nil];
}
let me know if you need explanation and/or further help
I think what you're looking for is a drill-down table interface.
Here's an example from Ray Wenderlich: http://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app. Also, here's the official reference from Apple: https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/TableViewAndDataModel/TableViewAndDataModel.html.
Good luck!
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.
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.