NSArray values becoming invalid or junky

Discussion in 'iOS Programming' started by superfahd, Jun 26, 2009.

  1. superfahd macrumors newbie

    Jun 26, 2009
    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:

    //  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;
    @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;
    #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
    The code for the database function that gets the class list:
    - (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];
    	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
  2. dejo Moderator


    Staff Member

    Sep 2, 2004
    The Centennial State
    Where and how do you declare classList? It's neither declared static in the .m nor synthesized.

Share This Page