I have an NSMutableArray that I want to populate with an sqlite database and display the data in a table view. The app builds and shows "database opened" in the console but just shows an empty tableview, I had it working perfectly but suddenly it seems to have stopped working. here is the code for adding the data to the array:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize entries;
- (void)viewDidLoad
{
[super viewDidLoad];
//[entries addObject:#"object1"];
//[entries addObject:#"object2"];
//[entries addObject:#"object3"];
//[entries addObject:#"object4"];
[self openDB];
entries = [[NSMutableArray alloc] init];
NSString *sql = [NSString stringWithFormat:#"SELECT * FROM speakers ORDER BY name"];
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];
[entries addObject:str ];
}
}
}
//file path to db
-(NSString *) filePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
return [[paths objectAtIndex:0] stringByAppendingPathComponent:#"speakerdb.sqlite"];
}
//open the db
-(void)openDB {
if (sqlite3_open([[self filePath] UTF8String], &db) != SQLITE_OK){
sqlite3_close(db);
NSAssert(0,#"error preparing statement: %s", sqlite3_errmsg(db));
}else{
NSLog(#"database opened");
}
}
The NSMutableArray is defined in the header file as follows:
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#import "speakerViewController.h"
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
IBOutlet UITableView *theTable;
sqlite3 *db;
}
#property (nonatomic,retain) NSMutableArray *entries;
#end
Here is the code for adding the data to 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
return [entries count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//Congigure the cell...
cell.textLabel.text = [entries objectAtIndex:indexPath.row];
return cell;
}
The data shows in the table view if I add objects to the array manually (commented out lines shown in the viewDidLoad method) but doesnt seem to work from the sqlite database.
Any help would be much appreciated.
Edit: I'm using xcode 5.1.1
Try to debug your code... Put a break point on NSString *field2Str = [[NSString alloc]initWithUTF8String:field2]; row, and check that field2 is not empty...
try to open db like this:
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"speakerdb"
ofType:#"sqlite"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
NSLog(#"Failed to open database!");
}
And one thing is missing from your code:
sqlite3_finalize(statement);
use it like this:
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];
[entries addObject:str ];
}
sqlite3_finalize(statement);
}
Related
I'm creating an iOS app which is a directory system, where on the first page I load data such as a list of some states in a tableview (from a sqlite database). When clicking on a state only the districts under that particular state have to be displayed in the detailview's tableview. My problem is that when clicking on each district the phonenumber of that district must be shown in the next view controller. Can somebody please help?
This is the firstview.
#implementation firstview
#synthesize ddetails=_ddetails;
#synthesize at,arraydata,show,table;
static firstview *_database;
+ (firstview*)database {
if (_database == nil) {
_database = [[firstview alloc] init];
}
return _database;}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [theauthors count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 30;}
- (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];
}
menu *me = [self.theauthors objectAtIndex:indexPath.row];
cell.textLabel.text=me.state;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
[_button setTitle:cellText forState:UIControlStateNormal];
menu *infos=[theauthors objectAtIndex:indexPath.row];
self.ddetails = [self.storyboard instantiateViewControllerWithIdentifier:#"detailViewController"] ;
_ddetails.uniqueId=infos.id;
// NSLog(#"%#",infos.state);
// NSLog(#"%d",infos.id);
[self.navigationController pushViewController:_ddetails animated:NO];
}
-(NSMutableArray *) authorList{
theauthors = [[NSMutableArray alloc]init] ;
show=[[NSMutableArray alloc]init];
#try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"menu.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 *query =[NSString stringWithFormat:#"SELECT id,category FROM category "];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(db, [query UTF8String], -1, &selectstmt, NULL) != SQLITE_OK)
{
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}else{
while (sqlite3_step(selectstmt)==SQLITE_ROW) {
menu * men = [[menu alloc] init];
men.id= sqlite3_column_int(selectstmt,0);
men.state=[NSString stringWithUTF8String:(char *) sqlite3_column_text(selectstmt,1)];
[theauthors addObject:men];
// NSLog(#"%#",men.category);
// NSLog(#"%d",men.id);
}
}
}
#catch (NSException *exception) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}
#finally {
sqlite3_close(db);
return theauthors;
}
}
- (detailsnews *)Detailsnews:(int)uniqueId{
NSLog(#"%d",uniqueId);
detailsnews *get=nil;
_the=[[NSMutableArray alloc]init];
_gets=[[NSMutableArray alloc]init];
#try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"menu.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 *sqls =[NSString stringWithFormat:#"SELECT * FROM menulist where category=%d",uniqueId];
// NSLog(#"%d",uniqueId);
sqlite3_stmt *selectstmt6;
if(sqlite3_prepare(db, [sqls UTF8String], -1, &selectstmt6, NULL) != SQLITE_OK)
{
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}else{
while (sqlite3_step(selectstmt6)==SQLITE_ROW) {
// NSLog(#"%d",uniqueid);
int totalValue = 0;
int uniqueId = sqlite3_column_int(selectstmt6,0);
// NSLog(#"%d",uniqueid);
[_gets addObject:[NSNumber numberWithInt:uniqueId]];
for(NSNumber *number in _gets) // Use fast enumeration to iterate through the array
{
totalValue = [number intValue];
// NSLog(#"%d",totalValue);
}
char *nameChars = (char *) sqlite3_column_text(selectstmt6, 2);
NSString *name = [[NSString alloc] initWithUTF8String:nameChars];
char *rec = (char *) sqlite3_column_text(selectstmt6, 1);
NSString *rece = [[NSString alloc] initWithUTF8String:rec];
// NSLog(#"%#",rece);
[_the addObject:rece];
NSMutableString * result = [[NSMutableString alloc] init];
for (NSObject * obj in _the)
{
[result appendString:[obj description]];
result = [_the componentsJoinedByString: #"\r"];
// NSLog(#"%#",result);
}
//[_the addObject:[NSNumber numberWithInt:uniqueid]];
// int totalValue = 0;
// for(NSNumber *number in _the) // Use fast enumeration to iterate through the array
// {
// totalValue = [number intValue];
// NSLog(#"%d",totalValue);
// }
//
// NSMutableString * result = [[NSMutableString alloc] init];
// int totalValue = 0;
//for (NSObject * obj in _the)
// {
// [result appendString:[obj description]];
// result = [_the componentsJoinedByString: #"\r"];
// NSLog(#"%#",result);
// }
//NSArray *arr=[result componentsSeparatedByString:#"\r"];
// NSMutableString * vgh = [[NSMutableString alloc] init];
// for (NSObject * obj in arr)
// {
//[vgh appendString:[obj description]];
// vgh = [arr componentsJoinedByString: #"\r"];
// }
get = [[detailsnews alloc] initWithUniqueId:totalValue district:result phonenumber:name ];
//NSLog(#"%#",_the);
}
}
}
#catch (NSException *exception) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}
#finally {
sqlite3_close(db);
return get;
}
}
detailview controller
- (void)viewDidLoad
{
[super viewDidLoad];
detailsnews *details = [[firstview database]
Detailsnews:_uniqueId];
if (details != nil) {
NSArray *arrComponents = [details.district componentsSeparatedByString:#"\r"];
arr = [[NSMutableArray alloc] init];
for(int i = 0; i < [arrComponents count] ;i++)
{
NSString *str = [arrComponents objectAtIndex:i];
[arr addObject:str];
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arr count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 30;}
- (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];
}
detailsnews *details = [[firstview database]
Detailsnews:_uniqueId];
cell.textLabel.text=[arr objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
[button2 setTitle:cellText forState:UIControlStateNormal];
detailsnews *details = [[firstview database]
Detailsnews:_uniqueId];
//NSLog(#"%d",details.uniqueId);
// NSLog(#"%#",details.rece);
// detailsnews *infos=[arr objectAtIndex:indexPath.row];
self.ddetails = [self.storyboard instantiateViewControllerWithIdentifier:#"phonelistViewController"] ;
_ddetails.uniqueId=details.uniqueId;
// NSLog(#"%d",details.uniqueId);
[self.navigationController pushViewController:_ddetails animated:NO];
}
You need to Pass the data including the phoneNumbers from first stateViewController to District and then from District to DetailsPage…I would suggest pass an NSdictionary which Includes the data from one view to another such as..In second ViewController declare a global Dictionary as mainDictionary..
and in didSelectRowAtIndexPath just pass the data as
self.ddetails = [self.storyboard instantiateViewControllerWithIdentifier:#"phonelistViewController"] ;
_ddetails.mainDict=AllThe Details;
Do the same thing with PhoneNumbers also
i'm korean my english so simple
very very sorry
please help me
my application example phone book.
two View and tab bar with sqlite3 DB
first view is table view cell list, there are name is linked DB
second view save and find and delete phone book list with SQL query.
i want secondview save data and change tab update data list.
i coded [viewDidAppear] reloadData method
close the application re-open apllication is updated.
but not updated change the tap T_T please help me.
FirstViewController.h
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#interface FirstViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSString *path;
NSString *dbName;
NSString *databasePath;
sqlite3 *contactDB;
}
#property (nonatomic) sqlite3 *contactDB_2;
#property (strong,nonatomic) IBOutlet UITableView *myTable;
#property (nonatomic,retain) NSMutableArray *quizs;
-(void)checkAndCreateDatabase;
-(void)readFromDatabase;
#end
FistViewController.m
#import "FirstViewController.h"
#import "person.h"
#implementation FirstViewController
#synthesize contactDB_2,myTable;
#synthesize quizs;
-(void)checkAndCreateDatabase{
NSFileManager *filemgr = [NSFileManager defaultManager];
if([filemgr fileExistsAtPath:databasePath] == NO){
const char *dbPath = [databasePath UTF8String];
if(sqlite3_open(dbPath,&contactDB) == SQLITE_OK){
char *errMsg;
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS CONTACTS(ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,ADRESS TEXT, PHONE TEXT)";
sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg);
sqlite3_close(contactDB);
}
}
}
-(void)readFromDatabase
{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if(sqlite3_open(dbpath, &contactDB)==SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT name,phone FROM contacts"];
const char *query_stmt = [querySQL UTF8String];
if(sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement)==SQLITE_ROW){
NSString* nameField = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement, 0)];
NSString* phoneField = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement, 1)];
person *persons = [person alloc];
[persons setName:nameField];
[persons setPhone:phoneField];
[quizs addObject:persons];
}
sqlite3_finalize(statement);
[myTable reloadData];
}
sqlite3_close(contactDB);
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"전화번호목록", #"전화번호목록");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
pragma mark - View lifecycle
- (void)viewDidLoad
{
dbName = #"contacts2.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:dbName];
[self checkAndCreateDatabase];
quizs = [[NSMutableArray alloc] initWithCapacity:100];
[self readFromDatabase];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[myTable delegate];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[quizs removeAllObjects];
[self checkAndCreateDatabase];
[self readFromDatabase];
[myTable reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return quizs.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];
}
person *p = [quizs objectAtIndex:indexPath.row];
NSString *str = [[NSString alloc]initWithFormat:#"%# %#",p.name,p.phone];
cell.textLabel.text = str;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = indexPath.row;
NSString *temp = [[NSString alloc]initWithFormat:#"%d번쨰꺼 선택해뜸",row+1];
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:#"터치" message:temp delegate:self cancelButtonTitle:nil otherButtonTitles:#"확인", nil];
[alert show];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
I want change the tab and update cell list.
Actually you can not insert the data in database in background .So until all data are inserted you have to keep application alive. If all data are saved successfully then please write reloadData code in ViewWillAppear.
First I would like to make clear that I do not want to use Core Data in this case.
My Problem: whenever my tableview's delegate methodd: numberOfRowsInSection is called, the application crashes with nothing more than an (lldb) error message.
First I have two classes which helps me retrieve rows from my SQLite database.
sqlite.m:
#import "sqlite.h"
#import <sqlite3.h>
#implementation sqlite
#synthesize carbohydrates = _carbohydrates;
#synthesize name = _name;
#synthesize fat = _fat;
#synthesize kcal = _kcal;
- (id)initWithName:(NSString *)name2 carbs:(NSNumber *)carbs2
fat:(NSNumber *)fat2 kcal:(NSNumber*)kcal2 {
if ((self = [super init])) {
self.carbohydrates = carbs2;
self.name = name2;
self.fat = fat2;
self.kcal = kcal2;
}
return self;
}
- (void) dealloc {
self.name = nil;
self.kcal = nil;
self.fat = nil;
self.carbohydrates = nil;
[super dealloc];
}
#end
NutritionsDB.m:
#import "NutritionsDB.h"
#import "sqlite.h"
#implementation NutritionsDB
static NutritionsDB *_database;
+ (NutritionsDB*)database {
if (_database == nil) {
_database = [[NutritionsDB alloc] init];
}
return _database;
}
- (id)init {
if ((self = [super init])) {
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"Livsmedeldatabas"
ofType:#"sqlite"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
NSLog(#"Failed to open database!");
}
}
return self;
}
- (void)dealloc {
sqlite3_close(_database);
[super dealloc];
}
-(void)setUpDB{
const char *sql_stmt = "CREATE INDEX IF NOT EXISTS name_index on livsmedel(namn)";
char *errMsg;
if (sqlite3_exec(_database, sql_stmt, NULL, NULL, &errMsg) == SQLITE_OK)
{
puts("Index successfully created");
// SQL statement execution succeeded
}
}
-(NSArray*)sqliteInfo:(NSString*)predicateString{
NSMutableArray *retval = [[[NSMutableArray alloc] init] autorelease];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [predicateString cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameChars = (char *) sqlite3_column_text(statement, 0);
char *kcalchars = (char *) sqlite3_column_text(statement, 1);
char *fatchars = (char *) sqlite3_column_text(statement, 2);
char *carbchars = (char *) sqlite3_column_text(statement, 3);
NSLog(#"\n%s, \n%s, \n%s", kcalchars, fatchars, carbchars);
NSString *name = [[NSString alloc] initWithUTF8String:nameChars];
NSString *kcal = [NSString stringWithFormat:#"%s", kcalchars];
NSString *fat = [NSString stringWithFormat:#"%s", fatchars];
NSString *carb = [NSString stringWithFormat:#"%s", carbchars];
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * kcalNumber = [f numberFromString:kcal];
NSNumber * fatNumber = [f numberFromString:fat];
NSNumber * carbNumber = [f numberFromString:carb];
NSLog(#"\n kcalnum : %#, \n fatnum: %#, \n carbnum : %#", kcalNumber, fatNumber, carbNumber);
[f release];
sqlite *info = [[sqlite alloc] initWithName:name carbs:carbNumber fat:fatNumber kcal:kcalNumber] ;
NSLog(#"%#,%#,%#,%#", name, kcal, fat, carb);
[retval addObject:info];
[name release];
[kcal release];
[fat release];
[carb release];
}
sqlite3_finalize(statement);
}
return retval;
}
#end
Now, In one of my viewcontrollers, I continuously make database calls via the method
-(NSArray*)sqliteInfo:(NSString*)predicateString.
predicateString is a copy of a text which the user enters in a search bar inside the VC.
In addition to the UISearchBar, the VC also holds a UITableView to represent the rows fetched from the databse.
Here is how I update the datasource contents and re-render the the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.nutritionList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"hej");
static NSString *CellIdentifier = #"NutritionIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.font = [UIFont fontWithName:#"Avenir-Medium" size:18.0];
cell.textLabel.text = [(sqlite*)[self.nutritionList objectAtIndex:indexPath.row] name];
return cell;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self.nutritionList removeAllObjects];
if (searchText.length < 2) {
;
} else {
NSString *firstChar = [searchText substringWithRange:NSMakeRange(0, 1)];
if([firstChar isEqualToString:#"å"] ||
[firstChar isEqualToString:#"Å"] ||
[firstChar isEqualToString:#"ä"] ||
[firstChar isEqualToString:#"Ä"] ||
[firstChar isEqualToString:#"ö"] ||
[firstChar isEqualToString:#"Ö"]){
NSString *lowerString = [firstChar lowercaseString];
NSString *upperString = [firstChar uppercaseString];
NSString *newSearchText = [searchText stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:lowerString];
NSString *newSearchText_upper = [searchText stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:upperString];
NSString *formatString = [[[[[#"'"stringByAppendingString:newSearchText]stringByAppendingString:#"%'"]
stringByAppendingString:#" OR namn like'"]stringByAppendingString:newSearchText_upper]stringByAppendingString:#"%' ORDER BY namn COLLATE NOCASE"];
NSArray *array = [[NutritionsDB database] sqliteInfo:[NSString stringWithFormat:#"Select * from livsmedel where namn like %#", formatString ]];
NSLog(#"%#",[NSString stringWithFormat:#"Select * from livsmedel where namn like %#", formatString ] );
for (sqlite *info in array) {
[self.nutritionList addObject:info];
}
}else{
NSString *formatString = [[#"'"stringByAppendingString:searchText]stringByAppendingString:#"%' "];
NSArray *array = [[NutritionsDB database] sqliteInfo:[NSString stringWithFormat:#"SELECT * FROM livsmedel WHERE namn LIKE %#", formatString ]];
NSLog(#"%#",[NSString stringWithFormat:#"Select * from livsmedel where namn like %#", formatString ] );
for (sqlite *info in array) {
[self.nutritionList addObject:info];
NSLog(#"carbs %#, fat %#, kcal %#", info.carbohydrates, info.fat, info.kcal);
}
}
}
[self.tableView reloadData];
}
Finally the crash occurs after the numberOfRowsInSection method is called, but before the cellForRowAtIndexPath is called. Somewhere between them.
The console says (lldb), nothing else. The view below is the assembly instructions that indicates where the crash occurs. However, I do not now how to interpret them.
My question: Why does this crash occur?
Thanks for your help.
How to join my two tables data into another screen in this Am Struck with the NSDictionary,NSArray and NSString how to add object into NSDictionary?
Below is my DBClass.m
#import "DBClass.h"
#implementation DBClass
+(NSString *)connectdb
{
NSArray *docDir=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dbFolder=[docDir objectAtIndex:0];
NSFileManager *manager=[NSFileManager defaultManager];
if (![manager fileExistsAtPath:dbFolder])
{
[manager createDirectoryAtPath:dbFolder withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *dbPath=[dbFolder stringByAppendingPathComponent:#"JoinsDB.sqlite"];
if (![manager fileExistsAtPath:dbPath])
{
[manager copyItemAtPath:[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"JoinsDB.sqlite"] toPath:dbPath error:nil];
}
NSLog(#"%#",dbPath);
return dbPath;
}
+(BOOL)createTable
{
NSString *dbpath=[DBClass connectdb];
sqlite3 *dbObj;
if (sqlite3_open([dbpath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_stmt *stmt=nil;
const char *sql="create table Company(ID INTEGER,Name VARCHAR,Age INTEGER,Address VARCHAR,Salary INTEGER)";
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"tabel created successfull");
}
else
{
NSLog(#"tabel already created");
}
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return YES;
}
+(int)saveData:(NSMutableArray *)data
{
sqlite3 *dbObj;
sqlite3_stmt *stmt=nil;
NSString *dbPath=[DBClass connectdb];
const char *sql=[[NSString stringWithFormat:#"insert into Company(ID,Name,Age,Address,Salary) values(\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")",[data objectAtIndex:0],[data objectAtIndex:1],[data objectAtIndex:2],[data objectAtIndex:3],[data objectAtIndex:4]]UTF8String];
if (sqlite3_open([dbPath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_bind_text(stmt, 1, [[data objectAtIndex:0]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [[data objectAtIndex:1]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [[data objectAtIndex:2]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, [[data objectAtIndex:3]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, [[data objectAtIndex:4]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"data insertion stmnt executed properly");
}
else
NSLog(#"data insertion stmnt not executed");
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return sqlite3_last_insert_rowid(dbObj);
}
+(BOOL)createTable2
{
NSString *dbpath=[DBClass connectdb];
sqlite3 *dbObj;
if (sqlite3_open([dbpath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_stmt *stmt=nil;
const char *sql="create table Department(ID INTEGER,Dept VARCHAR,Emp_ID INTEGER)";
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"tabel created successfull");
}
else
{
NSLog(#"tabel already created");
}
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return YES;
}
+(int)saveData2:(NSMutableArray *)data
{
sqlite3 *dbObj;
sqlite3_stmt *stmt=nil;
NSString *dbPath=[DBClass connectdb];
const char *sql=[[NSString stringWithFormat:#"insert into Department(ID,Dept,Emp_ID) values(\"%#\",\"%#\",\"%#\")",[data objectAtIndex:0],[data objectAtIndex:1],[data objectAtIndex:2]]UTF8String];
if (sqlite3_open([dbPath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_bind_text(stmt, 1, [[data objectAtIndex:0]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [[data objectAtIndex:1]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [[data objectAtIndex:2]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"data insertion stmnt executed properly");
}
else
NSLog(#"data insertion stmnt not executed");
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return sqlite3_last_insert_rowid(dbObj);
}
+(NSMutableArray *)getData
{
sqlite3 *dbobj;
NSString *dbpath =[DBClass connectdb];
NSMutableArray *readArray=[[NSMutableArray alloc]init];
if(sqlite3_open([dbpath UTF8String], &dbobj)==SQLITE_OK)
{
sqlite3_stmt *statement=nil;
//**** NSString *string=#"SELECT name FROM emptable";
NSString *string=#"SELECT EMP_ID, Age, DEPT FROM COMPANY INNER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID";
const char *query=[string UTF8String];
if(sqlite3_prepare_v2(dbobj, query, -1, &statement, NULL)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
NSMutableDictionary *readDic=[[NSMutableDictionary alloc] init];
[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)] forKey:#"Emp_ID"];
[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)] forKey:#"Name"];
[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)] forKey:#"Dept"];
[readArray addObject:readDic];
NSLog(#"%#",readDic);
}
}
sqlite3_finalize(statement);
}
NSLog(#"%#",readArray);
sqlite3_close(dbobj);
return readArray;
}
#end
How to show in UITableview,and in Viewdidload what should can I do
This my JoinViewController.m
#import "JoinViewController.h"
#import "DBClass.h"
#interface JoinViewController ()
#end
#implementation JoinViewController
#synthesize data,array;
#synthesize Table;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
array=[[NSMutableArray alloc]init];
data=[[NSMutableArray alloc]init];
array=[DBClass getData];
for( NSDictionary *obj in array)
{
NSLog(#"%#",obj);
[data addObject:[obj objectForKey:#"Emp_ID"]];
[data addObject:[obj objectForKey:#"Name"]];
[data addObject:[obj objectForKey:#"Dept"]];
}
NSLog(#"\n%d",[data count]);
[Table reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
//return 1;
return [data 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];
}
cell.textLabel.text = [[data objectAtIndex:indexPath.row]objectForKey:#"Emp_ID"];
cell.textLabel.text = [[data objectAtIndex:indexPath.row] objectForKey:#"Name"];
cell.textLabel.text = [[data objectAtIndex:indexPath.row] objectForKey:#"Dept"];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
#end
In your getdata method, your sql is asking for EMP_ID, Age, DEPT, but you're storing the data as Emp_ID, Name, Dept. One says age, the other says name. Also, you're duplicating the column numbers, getting a value from column 2, which would be DEPT, and you're storing it in Emp_ID, and you're getting the value from column 1 twice, which would be age, and storing it in Name and Dept. Column 0 should be Emp_ID, 1 is Age (which you probably want to change to Name), 2 is DEPT.
You can also simplify your SQL statement a bit with:
SELECT EMP_ID, Age, DEPT FROM COMPANY, DEPARTMENT where COMPANY.ID = DEPARTMENT.EMP_ID;
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: