I have image URL strings in database. Then I retrieving the images and add to productimg_array. I need to show the productimg_array images to UITableView cell. I'm using imageView.image=[UIImage imageNamed:[productimg_array objectAtIndex:indexPath.row]];
But app crashing.
const char *sql = "SELECT id,cat_id,product_image,order_by,description FROM product";
NSLog(#"sql is %s",sql);
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
// We "step" through the results - once for each row.
while (sqlite3_step(statement) == SQLITE_ROW) {
product_image = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 2)];
// NSLog(#"product_image is %#",product_image);
[productimg_array addObject:product_image];
}
}
TableView:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"productimg_array is %lu",(unsigned long)[productimg_array count]);
return [productimg_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
for(int i=0; i<[productimg_array count];i++){
[cell.imageView setImageWithURL:[NSURL URLWithString:[productimg_array objectAtIndex:i]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
cell.imageView.image = [productimg_array objectAtIndex:indexPath.row];
here cell.imageView.image expect an image in the position but the array has a set of strings that you are passing to set in the imageview
cell.imageView.image =[UIImage imageNamed:[productimg_array objectAtIndex:indexPath.row]];
Note :
product_image = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
can crash if the product_image is empty or null in db,so do this
char *nameChars = (char *) sqlite3_column_text(statement, 2);
if (nameChars) {
product_image = [[NSString alloc] initWithUTF8String:nameChars];
}
First you need to download that images from URL location and then you have to assign it to your image view.For this you can use lazy loading.
Related
I am developing IOS App, using Sqlite to Store data. Data can be shown on tableview and delete the row from table view and data can be remove form database sqlite. but when I delete row from tableview, app is crashing. And the error I am getting is :
Error:reason: 'Invalid update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update
(9) must be equal to the number of rows contained in that section
before the update (9), plus or minus the number of rows inserted or
deleted from that section (0 inserted, 1 deleted) and plus or minus
the number of rows moved into or out of that section (0 moved in, 0
moved out).
Thanks in Advance
Code :
NSMutableArray *resultArray
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
UITableViewCell *cell = [_tableview dequeueReusableCellWithIdentifier:#"cell"];
dataBase *data = [_arr objectAtIndex:indexPath.row];
UILabel *name = (UILabel *)[cell viewWithTag:1];
name.text = data.name;
UILabel *department = (UILabel *)[cell viewWithTag:2];
department.text = data.department;
UILabel *year = (UILabel *)[cell viewWithTag:3];
year.text = data.year;
if (indexPath.row %2 ==1) //Use for color on tableview
cell.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.9 alpha:1];
else
cell.backgroundColor = [UIColor colorWithRed:.8 green:.8 blue:.8 alpha:1];
return cell;
}
-(void)tableView:(UITableView *)_tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_tableView beginUpdates];
Sqlite *sqlite = [[Sqlite alloc]init];
[sqlite delete_profile:indexPath.row];
NSMutableArray *newA = [[sqlite resultArray] mutableCopy];
[newA removeObjectAtIndex:indexPath.row];
[_tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationRight];
[_tableView endUpdates];
}
[_tableView reloadData];
}
// Method to delete Row From Sqlite
-(void)delete_profile:(NSInteger)value
{
// _categoryArray = [[NSMutableArray alloc]init];
NSString *databasename=#"student.db"; // Your database Name.
NSArray * documentpath=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSAllDomainsMask, YES);
NSString * DocDir=[documentpath objectAtIndex:0];
NSLog(#"%#",DocDir);
NSString * databasepath=[DocDir stringByAppendingPathComponent:databasename];
if (sqlite3_open([databasepath UTF8String], &database) == SQLITE_OK)
{
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
NSString *sql = [NSString stringWithFormat:#"DELETE FROM studentsDetail WHERE regno=\"%ld\"",(long)value];
const char *sqlStatement = [sql cStringUsingEncoding:stringEncoding];
if (sqlite3_prepare_v2(database,
sqlStatement, -1, &statement, NULL) == SQLITE_OK)
{
//sqlite3_bind_int(statement, 1, value);
if (sqlite3_step(statement) == SQLITE_OK)
{
dataBase *base = [[dataBase alloc]init];
base.name = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
base.department = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
base.year = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
[_resultArray addObject:base];
}
}
else {
NSAssert1(0,#"Error preparing statement", sqlite3_errmsg(database));
}
}
}
No need for [_tableView reloadData]; after deleteRowsAtIndexPaths
Try this
-(void)tableView:(UITableView *)_tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
Sqlite *sqlite = [[Sqlite alloc]init];
[sqlite delete_profile:indexPath.row];
[resultArray removeObjectAtIndex:indexPath.row];
[_tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationRight];
}
}
I want to display images in a tableView from SQLite. Here is my retrieve image code from SQLite code. How do I load the images in the tableview?
-(void) retrieveData{
sqlite3 * database;
NSMutableArray *prodnamemutable = [[NSMutableArray alloc] init];
NSMutableArray *prodpricemutable = [[NSMutableArray alloc] init];
NSMutableArray *prodimagemutable = [[NSMutableArray alloc] init];
NSString *databasename=#"contacts.sqlite"; // Your database Name.
NSArray * documentpath=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSAllDomainsMask, YES);
NSString * DocDir=[documentpath objectAtIndex:0];
NSString * databasepath=[DocDir stringByAppendingPathComponent:databasename];
if(sqlite3_open([databasepath UTF8String], &database) == SQLITE_OK)
{
const char *sqlStatement = "SELECT * FROM contacts"; // Your Tablename
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
[prodnamemutable removeAllObjects];
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
[prodnamemutable addObject:[NSString stringWithFormat:#"%s",(char *) sqlite3_column_text(compiledStatement, 1)]];
[prodpricemutable addObject:[NSString stringWithFormat:#"%s",(char *) sqlite3_column_text(compiledStatement, 3)]];
int length = sqlite3_column_bytes(compiledStatement, 0);
NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(compiledStatement, 0) length:length];
[prodimagemutable addObject:imageData];
NSLog(#"Length from db : %lu", (unsigned long)[imageData length]);
imageArray = [NSArray arrayWithArray:prodimagemutable];
NSLog(#"image found.%#",imageArray);
}
}
nameArray = [[NSArray alloc]initWithArray:prodnamemutable];
priceArray = [[NSArray alloc]initWithArray:prodpricemutable];
NSLog(#"nameArray:%#",nameArray);
[[self navigationController] tabBarItem].badgeValue = [NSString stringWithFormat:#"%lu",(unsigned long)[nameArray count]];
sqlite3_finalize(compiledStatement);
[self.tableView reloadData];
}
sqlite3_close(database);
}
UIImage *image = [UIImage imageWithData:data];
This will convert your image NSData to UIImage now this image can be shown on any UIImageView.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; //count of section
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [prodimagemutable count]; //count number of row from image array.
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
}
cell.imageView.image = [UIImage imageWithData:[prodimagemutable objectAtIndex: indexpath.row]] ;
return cell;
}
//Below use for set height of cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;// or the height you want.
}
it will be better if you separated the code into multiple classes like the following
1. DBManager
#interface DBManager : NSObject
- (NSArray *)getImages;
#end
#implementation DBManager
- (NSArray *)getImages {
// put your code to retrieve the images from the database
// use the following to convert from NSData to UIImage
UIImage *image = [UIImage imageWithData:imageData];
}
#end
2. ImagesTableViewController
#interface ImagesTableViewController : UITableViewController
#property(nonatomic,strong) NSArray* images;
#end
#implementation ImagesTableViewController
- (void)viewDidLoad {
self.images = [dbManager getImages];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.images.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"myCell"];
}
cell.imageView.image = self.images[indexpath.row];
return cell;
}
#end
Hi I have a TableView that is populated by an sqlite database, I've set up a UISearchBar to filter it but it returns no results. Here is my code for the search bar:
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
if(text.length == 0)
{
isFiltered = FALSE;
}
else
{
isFiltered = true;
entriesFiltered = [[NSMutableArray alloc] init];
NSString *queryPart1 = #"SELECT * FROM table WHERE name LIKE '%";
NSString *queryPart2 = #"'% ORDER BY name";
NSString *sql = [NSString stringWithFormat:#"%#%#%#", queryPart1, text, queryPart2];
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);
NSString *field2Str = [[NSString alloc]initWithUTF8String:field2];
NSString *str = [[NSString alloc]initWithFormat:#"%#", field2Str];
[entriesFiltered addObject:str ];
}
sqlite3_finalize(statement);
}
}
[self.theTable reloadData];
}
Here is the code for the table view
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
//return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger)section
{
//Return the number of rows in the section
if(isFiltered){
return [entriesFiltered count];
} else {
return [entries count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Congigure the cell...
if(isFiltered){
cell.textLabel.text = [entriesFiltered objectAtIndex:indexPath.row];
return cell;
} else {
cell.textLabel.text = [entries objectAtIndex:indexPath.row];
return cell;
}
}
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.theTable indexPathForSelectedRow];
NSLog(#" indexPath row %ld",(long)indexPath.row);
speakerViewController *svc = [segue destinationViewController];
svc.labelText = descriptions[indexPath.row];
svc.url = urls[indexPath.row];
}
Is the problem the sql query for searching? Would it be better to just search the array instead of querying the database? if so how would i do this?
Any help would be much appreciated.
I have image URL strings in a database. Then I retrieve the images and add them to productimg_array. I need to show the images in table view cells. I used SDWebImage for download images from URL. But only one image displaying all the Cell.
const char *sql = "SELECT id,cat_id,product_image,order_by,description FROM product";
NSLog(#"sql is %s",sql);
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
// We "step" through the results - once for each row.
while (sqlite3_step(statement) == SQLITE_ROW) {
product_image = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 2)];
NSLog(#"product_image is %#",product_image);
[productimg_array addObject:product_image];
NSLog(#"productimg_arr is %#",productimg_array);
}
}
sqlite3_finalize(statement);
Table view:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"productimg_array is %lu",(unsigned long)[productimg_array count]);
return [productimg_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
for(int i=0; i<[productimg_array count];i++) {
[cell.imageView setImageWithURL:[NSURL URLWithString:[productimg_array objectAtIndex:i]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Log output:
productimg_arr is (
"http://server.net/projects/View/images/img.png",
"http://server.net/projects/View/images/img1.png",
"http://server.net/projects/View/images/img2.png",
"http://server.net/projects/View/images/img3.png",
"http://server.net/projects/View/images/img4.png",
"http://server.net/projects/View/images/img5.png",
"http://server.net/projects/View/images/img6.png"
)
Do this:
[cell.imageView setImageWithURL:[NSURL URLWithString:[productimg_array objectAtIndex:indexPath.row]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Then you will get different images in all cells.
Remove for loop from cellForRoeAtIndexPath and use indexPath.row instead of i.
Replace :
for(int i=0; i<[productimg_array count];i++){
[cell.imageView setImageWithURL:[NSURL URLWithString:[productimg_array objectAtIndex:i]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
By :
[cell.imageView setImageWithURL:[NSURL URLWithString:[productimg_array objectAtIndex:indexPath.row]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
I have a view controller where I have an add contact button and a table view. On clicking the add contact button a new view controller opens where there are a few textfields and labels and a button(Submit) which adds the textfield data to the database. I want that as I press the Submit button, the table view in the previous controller should contain the name and contact no. of the contact that was submitted. The addContact method is as follws:
-(IBAction)addContact{
sqlite3_stmt *statement;
const char *dbpath = [mDatabasePath UTF8String];
if (sqlite3_open(dbpath, &mDiary) == SQLITE_OK)
{
NSString *insertSQL1=[NSString stringWithFormat:#"INSERT INTO CONTACTS VALUES(\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")", mName.text, mContactno.text,mCemail.text,mClatitude.text,mClongitude.text];
const char *insert_stmt1 = [insertSQL1 UTF8String];
sqlite3_prepare_v2(mDiary, insert_stmt1,
-1, &statement, NULL);
NSString *tempName = [NSString stringWithFormat:#"%#",mName.text];
NSString *tempNo = [NSString stringWithFormat:#"%#",mContactno.text];
tempName = [tempName stringByAppendingString:tempNo];
[phoneContacts addObject:tempName];
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
if (sqlite3_step(statement) == SQLITE_DONE)
{ mStatus.text=#"Contact added";
mName.text=#"";
mContactno.text=#"";
mCemail.text=#"";
mClatitude.text=#"";
mClongitude.text=#"";
}
else {
mStatus.text = #"Failed to add contact";
}
sqlite3_finalize(statement);
sqlite3_close(mDiary);
}
}
The table view methods are:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.phoneContacts count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [self.phoneContacts objectAtIndex:indexPath.row];
return cell;
}
Nothing is getting shown in the table view. Why?
I've added a method populateContactTable:
-(IBAction)populateContactTable:(id)sender
{
sqlite3_stmt *statement;
const char *dbpath = [mDatabasePath UTF8String];
if (sqlite3_open(dbpath,&mDiary)== SQLITE_OK) {
NSString *selectSQL = [NSString stringWithFormat:#"SELECT * FROM CONTACTS"];
const char *query_stmt = [selectSQL UTF8String];
if (sqlite3_prepare_v2(mDiary,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
tempContactName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
tempContactNo = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement,1)];
tempContactName = [tempContactName stringByAppendingString:#" "];
tempContactName = [tempContactName stringByAppendingString:tempContactNo];
[phoneContacts addObject:tempContactName];
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
// NSLog(#"%#",userName);
// return tempContactName;
}
}
sqlite3_finalize(statement);
}
sqlite3_close(mDiary);
}
this method is called via a button in the root view controller. Still no data from the database is getting shown on the table.
Here's a snap of the storyboard: