How to assign from object to a cell in TableView? - ios5

In my iphon app , I'm reading from sqlite db into NSMutableArray *sales and I want to assign the data in sales into a cell in TableView.
How can I do it?
Here is my code:
In Controller:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *result = nil;
if ([tableView isEqual:self.myTableView]){
static NSString *TableViewCellIdentifier = #"MyCells";
result = [tableView dequeueReusableCellWithIdentifier:TableViewCellIdentifier];
if (result == nil){
result = [[UITableViewCell alloc]
initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier:TableViewCellIdentifier];
}
AppDelegate *appDelegate = ( AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate readSalesFromDatabase];
// ***here is where I'm trying to retrive the data***
// when I run the simulator, at this point I receive 'SIGABRT'
=====> result = [sales objectAtIndex:indexPath.row];
}
return result;
}
In Delegate:
-(void) readSalesFromDatabase {
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "select us.userID from UsersSale us order by us.saleID";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSInteger auserID = sqlite3_column_int(compiledStatement, 0);
// Create a new Sale object with the data from the database
SelectFromList *sfl = [[SelectFromList alloc] initWithName:auser];
// ***here is where I'm inserting the data to NSMutableArray *sales **
[selectFromListController.sales insertObject:sfl atIndex:count];
[sfl release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
#end

First, consider calling '[appDelegate readSalesFromDatabase]' on viewDidLoad or in your view controller's init method as you're invoking this for every row rendered. That's probably not what you want for performance.
Second, you should check to see what is in the 'sales' array and make sure there is data in it. If the indexPath.row value exceeds the size of the array, it's likely that you're not returning the actual and correct number of rows in 'tableView:numberOfRowsInSection:'. In that case, you're being asked for data that may not exist in your backing store.
Also, you may want to think of your UITableView usage not as 'assigning data into the table's cell' but instead, 'return data for the particular cell that is being rendered currently'.

Related

Iphone:Loading Limited Records In table View from Sqlite3 database

I have more than 100 records in a database of a particular user. Now I want to display only the first 30 from it, and when a "more" button is pressed, 30 more records will appear below them. How can I do it in an iPhone application?
You can use SQL Query to achieve your goal
-(NSMutableArray *)SelectResult:(int)offset
{
NSMutableArray *arrdata;
arrdata=[[NSMutableArray alloc]init];
sqlite3 *database;
NSString *databasePath = [self getDBPath];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *sqlQuery=[NSString stringWithFormat:#"Select * from TableName where RecordId > %d and RecordId <=%d",offset,offset+30];
sqlite3_stmt *compiledStatement;
compiledStatement=nil;
if(sqlite3_prepare_v2(database, [sqlQuery UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
if ((char *)sqlite3_column_text(compiledStatement,0)!=0)
{
NSMutableDictionary *temData = [[NSMutableDictionary alloc] init];
int pKey = sqlite3_column_int(compiledStatement,0);
[temData setValue:[NSString stringWithFormat:#"%d",pKey] forKey:#"RecordId"];
[arrdata addObject:temData];
}
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return arrdata;
}
Please call this method and pass offset as integer it will give you 30 recored from the offset
like offset = 0 then 1 to 30
offset = 30 then 31 to 60 etc....
Hope it will help you
Happy coding
Just use a NSMutableArray to hold you data. In your table view datasource make sure it displays an extra cell (with the "More" message) if there are any more records to display.
In didSelectRowAtIndexPath you can then modify the table view's data array by adding additional records from the database.
You can generate your SQL query dynamically based on the size of your data array.

How can I query a sqlite database using objective c?

I'm trying to display food by type to a user. The different types of foods are different elements in a table (fruits, veggies, meats, etc). I have all the foods in one database using sqlite. How can I query this database using objective c so that I can display only the correct type of food the user selected in the next view's table?
We use FMDB in two apps. It works fine.
-(NSArray *)GetAllFoods
{
NSMutableArray *filesArray = [[NSMutableArray alloc] init];
// Open the database from the users filessytem
NSString *DBPath = [ClsCommonFunctions GetDatabasePath];
if ([self OpenDBWithPath:DBPath])
{
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "your query";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(filesDB, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Need to get data from database...
NSSstring *foodObj = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]
[filesArray addObject:foodObj];
FileObj = nil;
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
sqlite3_close(filesDB);
}
return filesArray;

how to display the data getting from database in the table view in iphone

I have the two pages those are login and display page.when I click the submit button in login page then the second page is to be displayed with tableview of data getting from database.But I got the data from database and I need to display it in tableview .The problem is to display the data in the table view in xcode
I am taking the table view in .xib file
NSMutableArray *userArray = [NSMutableArray array];
int result = sqlite3_prepare_v2(itemdetails, sqlStatement, -1, &compiledStatement, NULL) ;
if( result == SQLITE_OK)
{
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSString *usernamedb = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSLog(#"dbvalue=%#",usernamedb);
NSLog(#"Count of rows:%d",count);
[itemcatg addObject:usernamedb];
}
}
sqlite3_finalize(compiledStatement);
then it give the error in adding subview to the submit button in login page as in below line of code
[self presentModalViewController:subview animated:YES];
Using a an SQLite abstraction such as the following will help:
https://github.com/jameswomack/CCData
That set of classes allows you to easily get SQLite data into native objects such as NSArray so you can do this:
cell.text = [arrayFromDatabase objectAtIndex:indexPath.row];

Strange behavior with NSObject Properties

I have an NSObject that I am using to store/hold properties of an object, one of them being a "Name" property cast as an NSString. I am also pulling data from a SQLite DB for said object using the following:
- (void) getDataToDisplay:(NSString *)dbPath {
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
NSString *queryOnStyle = [NSString stringWithFormat:
#"SELECT WineId, Name FROM wine WHERE StyleId = %d", dataManager.styleId];
const char *sql = [queryOnStyle UTF8String];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
Wine *w = [[Wine alloc] init];
w.wineId = sqlite3_column_int(selectstmt, 0);
w.wineName = [NSString stringWithUTF8String:
(char *)sqlite3_column_text(selectstmt, 1)];
[dataManager.wines addObject:w];
[w release];
}
}
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
Wine being my object. If I were to log w.wineName at this point, there is no problem. The problem occurs later when I try to access the properties of the object from within the array, dataManager.wines, in a custom tableView. It suddenly treats my wineName as a UIImageView rather than an NSString...
I for the life of me cannot trace anything back to ever being cast as a UIImageView and have no idea why it would be setting just that property as such. Here is the code for my custom tableView:
#pragma mark -
#pragma mark HorizontalTableViewDelegate methods
- (NSInteger)numberOfColumnsForTableView:(HorizontalTableView *)tableView {
return [dataManager.wines count];
}
- (UIView *)tableView:(HorizontalTableView *)aTableView viewForIndex:(NSInteger)index {
UIView *vw = [aTableView dequeueColumnView];
if (!vw) {
[[NSBundle mainBundle] loadNibNamed:#"ColumnView" owner:self options:nil];
vw = self.columnView;
self.columnView = nil;
}
// Get the wineId from the array of wineId integers
Wine *w = [dataManager.wines objectAtIndex:index];
int tempWineId = w.wineId;
NSString *tempWineName = [NSString stringWithFormat:#"%#", w.wineName];
NSLog(#"%#", tempWineName); \\RETURNS TEMPWINENAME AS A UIIMAGEVIEW
[w release];
return vw;
}
- (CGFloat)columnWidthForTableView:(HorizontalTableView *)tableView {
//TODO: This value needs to change if changed in IB
return 209.0f;
}
any ideas?
Resolved in comments of question by RichB:
is w.wineName a retain'ed property ? This sounds a bit like the string is being auto released. Could you post the definition of the Wine object?

How to reset array in multiview iphone app

I am trying to have a tableview that leads to another tableview whose list items depend on the first view. I have the database set up properly and my problem is that when I select one item on the first page and go to the second view for the first time it works fine but when I return to the first page and go back to the second view again the list still has the old values loaded with new ones. Is there a way to destroy the array and recreate it every time the second view is loaded? Where would I do this?
Here is where my array is initialized in the delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self copyDatabaseIfNeeded];
organArray = [[NSMutableArray alloc] init];
procedureArray = [[NSMutableArray alloc] init];
[Organ getInitialDataToDisplay:[self getDBPath]];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
Here is where the data is added to the array in my custom class:
+ (void) getDatabase:(NSString *)dbPath WithOrganID:(NSNumber *)organID
{
RadiologyAppAppDelegate *appDelegate = (RadiologyAppAppDelegate *)[[UIApplication sharedApplication] delegate];
if(sqlite3_open([dbPath UTF8String],&database) == SQLITE_OK){
const char *sql = "select * from Organ";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK){
while (sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Procedure *procedureObj = [[Procedure alloc] initWithPrimaryKey:primaryKey];
procedureObj.procedureName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)];
procedureObj.procedureID = sqlite3_column_int(selectstmt,0);
[appDelegate.procedureArray addObject: procedureObj];
[procedureObj release];
}
}
}
else
sqlite3_close(database);
}
Finally, here is my view controller:
- (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] autorelease];
}
Procedure *procedureObj = [appDelegate.procedureArray objectAtIndex:indexPath.row];
PVCprocedureObj = appDelegate.procedureArray;
cell.textLabel.text = procedureObj.procedureName;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Thanks for the help!
I would pass the data-object (data to be shown in the second table) to the 2nd controller. I think this is the easiest approach and you are not showing that part.
Pass the object when clicking the cell, inside: – tableView:didSelectRowAtIndexPath: and not when making the cell: -tableView:cellForRowAtIndexPath:
Hope this helps