Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

superfahd

macrumors newbie
Original poster
Jun 26, 2009
1
0
Hi guys

My first post here!

I've been programming on the IPhone for about 2 weeks now and today came across a really confusing problem :confused:. I'm writing a fairly complex application and the code I'm pasting below is one of its view controllers. I realize that the code is extremely messy right now but that's after tons of different experiments. I'll try to explain as much as I can.

Its an application for a school and I'm trying to go in the code below to show a teacher's name and a list of classes that she's teaching in a UITableView.

The problem is that the class list is being fetched from the database fine but at the moment I try to use it as my data source (in the function (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath ), its entries either become invalid or contain junk values. The number of entries in the list doesn't change however.

The objects and functions to the problem are:

EdugenceAppDelegate is my application delegate which contains a database access object, called database, that has data access methods (eg getClassesForTeacher)

SchoolClass is the object representing a class. it has 2 variables: classID and classTitle both of which are NSString *

Teacher represents a teacher. The only relevant variable in it is teacherID which is used in the where clause of the query that fetches the class list.

The place to start would be viewDidLoad where i make the database call. As I said earlier, at the end of this function, the list of classes is properly fetched and assigned to the controllers own classList variable. By the time I get to the table view's data source methods, everything is junky

The code for the view controller:

Code:
//
//  CourseViewController.m
//  EMobile
//
//


#import "ClassSelectionController.h"
#import "StudentSelectionController.h"
#import "EditTeacherController.h"
#import "EdugenceAppDelegate.h"
#import "DatabaseAccess.h"
#import "SchoolClass.h"
#import "Teacher.h"

static NSString *cellIdentifier = @"MyIdentifier";

#pragma mark Private Methods
@interface ClassSelectionController (Private)

- (void)loadStudentSelectionController;
- (void)loadEditTeacherController;
- (NSArray *)fetchClassList;
- (NSString *)fetchTeacherName;

@end

@implementation ClassSelectionController (Private)

- (void)loadStudentSelectionController 
{
	StudentSelectionController *studentSelectionController = [[StudentSelectionController alloc] initWithNibName:@"StudentSelection" bundle:[NSBundle mainBundle]];
	[self.navigationController pushViewController:studentSelectionController animated:YES];
	[studentSelectionController release];
	studentSelectionController = nil;
}

- (void)loadEditTeacherController 
{
	EditTeacherController *editTeacherController = [[EditTeacherController alloc] initWithNibName:@"EditTeacher" bundle:[NSBundle mainBundle]];
	[[self navigationController] pushViewController:editTeacherController animated:YES];
	[editTeacherController release];
	editTeacherController = nil;
}

- (NSArray *)fetchClassList 
{
	EdugenceAppDelegate *appDelegate = (EdugenceAppDelegate *) [[UIApplication sharedApplication] delegate];
	Teacher *teacher = appDelegate.loggedInTeacher;
	NSMutableArray *mutableList = [appDelegate.database getClassesForTeacher:teacher];
	NSArray *staticList = [[NSArray alloc] initWithArray:mutableList];
	mutableList = nil;
	[mutableList release];
	return staticList;
}

- (NSString *)fetchTeacherName 
{
	EdugenceAppDelegate *appDelegate = (EdugenceAppDelegate *) [[UIApplication sharedApplication] delegate];
	return appDelegate.loggedInTeacher.teacherName;
}

@end

#pragma mark -
#pragma mark Public Methods

@implementation ClassSelectionController

@synthesize teacherNameLabel;

#pragma mark UITableViewDelegate methods

// decide what kind of accesory view (to the far right) we will use
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
	return UITableViewCellAccessoryDisclosureIndicator;
}

// tell our table how many sections or groups it will have (always 1 in our case)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
	return 1;
}

// the table's selection has changed, switch to that item's UIViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
	[self loadStudentSelectionController];
}

// the table's title
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
	return @"Select a class";
}

#pragma mark -
#pragma mark UITableViewDataSource methods

// tell our table how many rows it will have, in our case the size of our menuList
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	return [classList count];
}

// tell our table what kind of cell to use and its title for the given row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
	if (cell == nil)
	{
		cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease];
	}
	
	SchoolClass *schoolClass = (SchoolClass *)[classList objectAtIndex:indexPath.row];
	cell.text = schoolClass.classTitle;	
	return cell;
}

#pragma mark -
#pragma mark UIViewController methods

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad 
{
    [super viewDidLoad];
	
	NSArray *list = [[NSArray alloc] init];
	list = [self fetchClassList];
	classList = [[NSArray alloc] initWithArray:list copyItems:YES];
	
	list = nil;
	[list release];
	
	NSString *teacherName = [[NSString alloc] initWithFormat:@"This device is currently registered to %@", [self fetchTeacherName]];
	teacherNameLabel.text = teacherName;
	[teacherName release];
	
	[self.navigationItem setBackBarButtonItem:nil];
	self.navigationItem.title = @"Classes";
}

- (void)didReceiveMemoryWarning 
{
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

- (void)dealloc {
	[classList release];
	[teacherNameLabel release];
    [super dealloc];
}

#pragma mark -
#pragma mark event handlers

- (void)editTeacherSelector:(id)sender
{
	[self loadEditTeacherController];
}

- (void)logoutSelector:(id)sender 
{
	//do logout stuff
	[self.navigationController popToRootViewControllerAnimated:YES];
}
#pragma mark -
#pragma mark Unimplemented default methods

/*
 // The designated initializer. Override to perform setup that is required before the view is loaded.
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
 if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
 // Custom initialization
 }
 return self;
 }
 */

/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
	 [super loadView];	
 }
*/

/*
 // Override to allow orientations other than the default portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 // Return YES for supported orientations
 }
 */
@end

The code for the database function that gets the class list:
Code:
- (NSMutableArray *)getClassesForTeacher:(Teacher *)teacher
{
	NSMutableArray *listOfClasses = [[NSMutableArray alloc] init];
	
	//open the database
	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) 
	{
		const char *sql = 
		"SELECT ClassID, ClassTitle "
		"FROM Classes "
		"WHERE TeacherID = ?";
		
		sqlite3_stmt *selectStatement;	
		//prepare the statement
		if (sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL) != SQLITE_OK) 
			NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
		
		//bind teacherID to placeholder (placeholder count starts from 1)
		sqlite3_bind_text(selectStatement, 1, [teacher.teacherID UTF8String], -1, SQLITE_TRANSIENT);
		
		//run query and loop through results
		while (sqlite3_step(selectStatement) == SQLITE_ROW) 
		{
			NSString *ID = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectStatement, 0)];
			NSString *title = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectStatement, 1)];
			
			SchoolClass *schoolClass = [[SchoolClass alloc] initWithID:ID Title:title];
			[listOfClasses addObject:schoolClass];

			ID = nil;
			[ID release];
			title = nil;
			[title release];
			schoolClass = nil;
			[schoolClass release];
		}
		
		sqlite3_finalize(selectStatement);
		sqlite3_close(database);
	}
	else 
		sqlite3_close(database);
	
	return listOfClasses;
}

I hope this is enough. Please let me know if there is anything else needing clarification. Heck I'll even attach my whole application if someone wants
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.