DESCRIPTION OF THE APPLICATION . I am a new iPhone developer. I am working on an application that used two kinds of tables, and then a detailed view. The first level table view presents several categories, when a category is selected, a list of topics related to this category is displayed. When a theme is selected, a detailed view is presented associated with this theme.
When I run the application in the simulator, everything works fine (but only for a short while!):
- First level table: this view with the category loads perfectly and works without problems.
- View topic list: This view also works fine, but only for a short while. It downloads all the correct themes, and I can even quickly scroll up and down the entire list of topics, but this only works for a couple of seconds when scrolling (after which the application crashes). I can also select any of the topics and upload a detailed view.
- Detailed view: working fine, no problem.
I use two applications for the application: MainWindow.xib displays the first level tables and themes. The themeDetail.xib is used to display detailed information for the theme.
The DATA: . The first level of viewing gets its data from plist, which consists of an array of strings. Viewing a list of topics gets its data from the dictionary layer. Each dictionary consists of five lines. One of these lines contains “Tags” for categories that relate to the topic. When a category is selected from a first-level view, in the "Topic" section, topics are selected with "Tags" that correspond to the selected category, and displays them in the "View Topic" table.
PROBLEM: My problem is with the second "View Topic". A few ways I was able to cause a crash:
: , , EXC_BAD_ACCESS. NSZombieEnabled, " - [ CFString]: ,
, , , "" , , , ! - !
CODE:
View Controller.h:
#import
@class TopicListController;
@interface FirstLevelViewController : UITableViewController {
NSArray *controllers;
TopicListController *childController;
}
@property (nonatomic, retain) NSArray *controllers;
@end
.m:
#import "FirstLevelViewController.h"
#import "TopicListController.h"
#import "TopicAppDelegate.h"
@implementation FirstLevelViewController
@synthesize controllers;
- (void)viewDidLoad
{
self.title = @"Categories";
NSString *path = [[NSBundle mainBundle] pathForResource:@"TopicCategoryList" ofType:@"plist"];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
self.controllers = array;
[array release];
[super viewDidLoad];
}
- (void)viewDidUnload
{
self.controllers = nil;
[childController release];
childController = nil;
[super viewDidUnload];
}
- (void) dealloc
{
[controllers release];
[childController release];
[super dealloc];
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableview numberOfRowsInSection:(NSInteger)section
{
return [self.controllers count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *FirstLevelCell = @"FirstLevelCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:FirstLevelCell];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstLevelCell] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [controllers objectAtIndex:row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark -
#pragma mark Table View Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (childController == nil) {
childController = [[TopicListController alloc] init];
}
childController.title = @"Topics";
NSUInteger row = [indexPath row];
NSString *selectedCategory = [self.controllers objectAtIndex:row];
childController.selectedCategory = selectedCategory;
[self.navigationController pushViewController:childController animated:YES];
}
@end
Controller.h:
#import
@class TopicDetailController;
@interface TopicListController : UITableViewController {
NSArray *list;
NSString *selectedCategory;
TopicDetailController *childController;
}
@property (nonatomic, retain) NSArray *list;
@property (nonatomic, retain) NSString *selectedCategory;
@end
.
#import "TopicListController.h"
#import "TopicAppDelegate.h"
#import "TopicDetailController.h"
#import "NSArray-MutableDeepCopy.h"
#import "TopicConstants.h"
@implementation TopicListController
@synthesize list;
@synthesize selectedCategory;
- (void)viewWillAppear:(BOOL)animated
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"TopicContent" ofType:@"plist"];
NSMutableArray *fullArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
NSMutableArray *fullArrayCopy = [fullArray mutableDeepCopy];
NSUInteger items = [fullArrayCopy count];
NSUInteger item=0;
for (item; item items; item++) {
if ([[[fullArrayCopy objectAtIndex:item] objectForKey:CATEGORIES_KEY]
rangeOfString:selectedCategory
options:NSCaseInsensitiveSearch].location == NSNotFound)
{
[fullArrayCopy removeObjectAtIndex:item];
item--;
items--;
}
}
self.list = fullArrayCopy;
[fullArray release];
[self.tableView reloadData];
[super viewWillAppear:animated];
}
- (void)viewDidUnload
{
self.list = nil;
self.selectedCategory = nil;
[childController release];
childController = nil;
}
- (void)dealloc
{
[list release];
[selectedCategory release];
[childController release];
[super dealloc];
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section
{
return [list count];
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath
{
static NSString *DisclosureButtonCellIdentifier = @"DisclosureButtonCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DisclosureButtonCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:DisclosureButtonCellIdentifier]
autorelease];
}
NSUInteger row = [indexPath row];
NSString *rowString = [[list objectAtIndex:row] objectForKey:TITLE_KEY];
NSString *rowDetailString = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY];
cell.textLabel.text = rowString;
cell.detailTextLabel.text = rowDetailString;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
[rowString release];
[rowDetailString release];
return cell;
}
#pragma mark -
#pragma mark Table Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (childController == nil) {
childController = [[TopicDetailController alloc] initWithNibName:@"TopicDetail" bundle:nil];
}
NSUInteger row = [indexPath row];
NSString *selectedTopicInformation = [[list objectAtIndex:row] objectForKey:INFORMATION_KEY];
NSString *selectedTopicTitle = [[list objectAtIndex:row] objectForKey:TITLE_KEY];
NSString *selectedTopicSubtitle = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY];
NSString *selectedTopicTips = [[list objectAtIndex:row] objectForKey:TIPS_KEY];
NSString *detailMessageInformation = [[NSString alloc] initWithFormat:@"%@.", selectedTopicInformation];
NSString *detailMessageTitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicTitle];
NSString *detailMessageSubtitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicSubtitle];
NSString *detailMessageTips = [[NSString alloc] initWithFormat:@"%@", selectedTopicTips];
childController.messageInformation = detailMessageInformation;
childController.messageTitle = detailMessageTitle;
childController.messageSubTitle = detailMessageSubtitle;
childController.messageTips = detailMessageTips;
childController.title = @"Topic Detail";
[detailMessageInformation release];
[detailMessageTitle release];
[detailMessageSubtitle release];
[detailMessageTips release];
[self.navigationController pushViewController:childController animated:YES];
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
if (childController == nil) {
childController = [[TopicDetailController alloc] initWithNibName:@"TopicDetail" bundle:nil];
}
NSUInteger row = [indexPath row];
NSString *selectedTopicInformation = [[list objectAtIndex:row] objectForKey:INFORMATION_KEY];
NSString *selectedTopicTitle = [[list objectAtIndex:row] objectForKey:TITLE_KEY];
NSString *selectedTopicSubtitle = [[list objectAtIndex:row] objectForKey:SUBTITLE_KEY];
NSString *selectedTopicTips = [[list objectAtIndex:row] objectForKey:TIPS_KEY];
NSString *detailMessageInformation = [[NSString alloc] initWithFormat:@"%@.", selectedTopicInformation];
NSString *detailMessageTitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicTitle];
NSString *detailMessageSubtitle = [[NSString alloc] initWithFormat:@"%@", selectedTopicSubtitle];
NSString *detailMessageTips = [[NSString alloc] initWithFormat:@"%@", selectedTopicTips];
childController.messageInformation = detailMessageInformation;
childController.messageTitle = detailMessageTitle;
childController.messageSubTitle = detailMessageSubtitle;
childController.messageTips = detailMessageTips;
childController.title = @"Topic Detail";
[detailMessageInformation release];
[detailMessageTitle release];
[detailMessageSubtitle release];
[detailMessageTips release];
[self.navigationController pushViewController:childController animated:YES];
}
@end