Like so many people commenting on here, I am new to the world of Iphone development. I am hoping someone can point out to me why my code keeps crashing. Neither the debugger nor the console is providing me with useful feedback.
I am trying to create a simple dictionary using a tableview. I need the Terms to have their first letter as a key and the term to bind to the tableview.
The datasource is a plist that is formatted as such but shrunk for readability here:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>Term</key>
<string>TERM1</string>
<key>Definition</key>
<string>DEFINITION1</string>
</dict>
<dict>
<key>Term</key>
<string>TERM2</string>
<key>Definition</key>
<string>DEFINITION2</string>
</dict>
</array>
</plist>
I have a model class as follows:
TermsAndDefinitions.h
Code:
#import <Foundation/Foundation.h>
@interface TermsAndDefinitions : NSObject
{
NSString *Term;
NSString *Definition;
}
- (id)initWithDictionary:(NSDictionary *)aDictionary;
@property (nonatomic, retain) NSString *Term;
@property (nonatomic, retain) NSString *Definition;
@end
TermsAndDefinitions.m
Code:
#import "TermsAndDefinitions.h"
@implementation TermsAndDefinitions
@synthesize Term;
@synthesize Definition;
- (id)initWithDictionary:(NSDictionary *)aDictionary {
if ([self init]) {
self.Term = [aDictionary valueForKey:@"Term"];
self.Definition = [aDictionary valueForKey:@"Definition"];
}
return self;
}
- (void)dealloc {
[Term release];
[Definition release];
[super dealloc];
}
@end
Definitions.h
Code:
#import <UIKit/UIKit.h>
#import "TermsAndDefinitions.h"
@interface Definitions : UIViewController
<UITableViewDataSource, UITableViewDelegate>
{
NSMutableDictionary *definitionsDictionary;
NSMutableDictionary *nameIndexesDictionary;
TermsAndDefinitions *eachTermAndDefinition;
NSArray *termsNameIndexArray;
}
@property (nonatomic,retain) NSMutableDictionary *nameIndexesDictionary;
@property (nonatomic,retain) NSMutableDictionary *definitionsDictionary;
@property (nonatomic, retain) TermsAndDefinitions *eachTermAndDefinition;
@property (nonatomic,retain) NSArray *termsNameIndexArray;
@end
Definitions.m
Code:
#import "Definitions.h"
#import "LP_1_0AppDelegate.h"
@interface Definitions(mymethods)
- (void)presortTermNamesForInitialLetter:(NSString *)aKey;
- (void)presortDefinitionLetterIndexes;
@end
@implementation Definitions
@synthesize definitionsDictionary;
@synthesize nameIndexesDictionary;
@synthesize eachTermAndDefinition;
@synthesize termsNameIndexArray;
- (void)viewDidLoad {
NSDictionary *eachTerm;
// create dictionaries that contain the arrays of element data indexed by Term
self.definitionsDictionary = [NSMutableDictionary dictionary];
// unique first characters (for the Name index table)
self.nameIndexesDictionary = [NSMutableDictionary dictionary];
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"Definitions" ofType:@"plist"];
NSArray *rawTermsAndDefinitionsArray = [[NSArray alloc] initWithContentsOfFile:thePath];
// iterate over the values in the raw elements dictionary
for (eachTerm in rawTermsAndDefinitionsArray)
{
// create an Term and Definition instance for each
TermsAndDefinitions *aTermAndDefinition = [[TermsAndDefinitions alloc] initWithDictionary:eachTerm];
// store the item in the terms and definitions dictionary with the Term as the key
[definitionsDictionary setObject:aTermAndDefinition forKey:aTermAndDefinition.Term];
// get the term's initial letter
NSString *firstLetter = [aTermAndDefinition.Term substringToIndex:1];
NSMutableArray *existingArray;
// if an array already exists in the term index dictionary
// create an array and add it to the term index dictionary with the letter as the key
if (existingArray = [nameIndexesDictionary valueForKey:firstLetter])
{
[existingArray addObject:aTermAndDefinition];
} else {
NSMutableArray *tempArray = [NSMutableArray array];
[nameIndexesDictionary setObject:tempArray forKey:firstLetter];
[tempArray addObject:aTermAndDefinition];
}
// release the Term and Definition, it is held by the various collections
[aTermAndDefinition release];
}
// release the raw terms data
[rawTermsAndDefinitionsArray release];
[self presortDefinitionLetterIndexes];
}
// return an array of terms for an initial letter (ie A, B, C, ...)
- (NSArray *)termsWithInitialLetter:(NSString*)aKey {
return [nameIndexesDictionary objectForKey:aKey];
}
// presort the name index arrays so the terms are in the correct order
- (void)presortDefinitionLetterIndexes {
self.termsNameIndexArray = [[nameIndexesDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
for (NSString *eachNameIndex in termsNameIndexArray) {
[self presortTermNamesForInitialLetter:eachNameIndex];
}
}
- (void)presortTermNamesForInitialLetter:(NSString *)aKey {
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Term"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)] ;
NSArray *descriptors = [NSArray arrayWithObject:nameDescriptor];
[[nameIndexesDictionary objectForKey:aKey] sortUsingDescriptors:descriptors];
[nameDescriptor release];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
self.definitionsDictionary = nil;
self.nameIndexesDictionary = nil;
self.eachTermAndDefinition = nil;
[super viewDidUnload];
}
- (void)dealloc {
[definitionsDictionary release];
[nameIndexesDictionary release];
[eachTermAndDefinition release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [termsNameIndexArray count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{ return termsNameIndexArray; }
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return index;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// the section represents the initial letter of the term
// return that letter
NSString *initialLetter = [termsNameIndexArray objectAtIndex:section];
// get the array of terms that begin with that letter
NSArray *termsWithInitialLetter = [termsWithInitialLetter:initialLetter];
// return the count
return [termsWithInitialLetter count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// this table has multiple sections. One for each unique character that a term begins with
// [A,B,C,D,E,F,G,H,I,K,L,M,N,O,P,R,S,T,U,V,X,Y,Z]
// return the letter that represents the requested section
return [termsNameIndexArray objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [termsNameIndexArray objectAtIndex:section];
NSArray *termsSection = [nameIndexesDictionary objectForKey:key];
sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SectionsTableIdentifier] autorelease];
}
cell.textLabel.text = [termsSection objectAtIndex:row];
return cell;
}
@end
I am usually all for working through an issue but it has been a few days now and I cannot see it. I am hoping it is something silly that I just do not get in Ojective C.
Thanks
Dave