Evening,
I have managed to section my table alphabetically (:D) but now the cells do not select.
The idea is that the first view presents a list of words. A word is then selected and that leads to a detail view featuring a glossary. But, the cell doesn't select (turns grey not blue?) and the segue in storyboard running from prototype cell to new view doesn't do anything (clicking a cell in simulator doesn't cause the segue).
Does anyone have a suggestion?
I have included my code below, with the prepareforsegue code ready for when needed.
Thanks guys :)
#interface RCViewController ()
#end
#implementation RCViewController
static NSString *CellIdentifier = #"Cell Identifier";
#synthesize fruits;
-(NSDictionary *)alphabetizedFruits:(NSArray *)fruitsArray {
NSMutableDictionary *buffer = [[NSMutableDictionary alloc]init];
for (int i=0; i <fruits.count; i++) {
NSString *fruit = [fruits objectAtIndex:i];
NSString *firstLetter = [[fruit substringToIndex:1]uppercaseString];
if ([buffer objectForKey:firstLetter]) {
[(NSMutableArray *)[buffer objectForKey:firstLetter]addObject:fruit];
}
else {
NSMutableArray *mutableArray = [[NSMutableArray alloc]initWithObjects:fruit, nil];
[buffer setObject:mutableArray forKey:firstLetter];
}
}
NSArray *keys = [buffer allKeys];
for (int j; j<keys.count; j++) {
NSString *key = [keys objectAtIndex:j];
[(NSMutableArray *)[buffer objectForKey:key]sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
NSDictionary *result = [NSDictionary dictionaryWithDictionary:buffer];
return result;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSArray *keys = [self.alphabetizedFruits allKeys];
return [keys count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *unsortedKeys = [self.alphabetizedFruits allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:section];
NSArray *fruitsForSection = [self.alphabetizedFruits objectForKey:key];
return [fruitsForSection count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSArray *unsortedKeys = [self.alphabetizedFruits allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:[indexPath section]];
NSArray *fruitsForSection = [self.alphabetizedFruits objectForKey:key];
NSString *fruit = [fruitsForSection objectAtIndex:[indexPath row]];
[cell.textLabel setText:fruit];
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSArray *keys = [[self.alphabetizedFruits allKeys]sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [keys objectAtIndex:section];
return key;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
detailViewController *destViewController = segue.destinationViewController;
destViewController.word = [fruits objectAtIndex:indexPath.row];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *path = [[NSBundle mainBundle]pathForResource:#"words" ofType:#"plist"];
NSArray *wordsDictionary = [NSArray arrayWithContentsOfFile:path];
self.fruits = [wordsDictionary valueForKey:#"Word"];
self.alphabetizedFruits = [self alphabetizedFruits:self.fruits];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
you need to add the didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// confirm cell is being selected
NSLog(#"didSelectRowAtIndexPath");
// perform the segue by getting the cell selected and passing it to the prepareForSegue method
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"showDetail" sender:cell];
}
Related
I have the following code. It results in a sectioned uitableview. However, the words in each section are in reverse order (r before a, x before t). I have tried to use nsdescriptor and selectors in various parts of the code but it results in Xcode throwing nsexception ncsf dictionary invalid selector sent localisedcaseinsensitivecompare. This only occurs when I fiddle with the above - even if I don't add localisedCaseInsensitiveCompare (it works with those instances that are already in place).
Any fresh eyes able to solve this.
Thanks
#implementation RCViewController
static NSString *CellIdentifier = #"Cell Identifier";
#synthesize words;
#synthesize alphabetizedWords;
#synthesize wordDictionary;
#synthesize keys;
-(NSDictionary *)alphabetizedWords:(NSArray *)wordsArray {
NSMutableDictionary *buffer = [[NSMutableDictionary alloc]init];
for (int i=0; i <wordsArray.count; i++) {
NSDictionary *keyValue = [wordsArray objectAtIndex:i];
NSString *word = [[wordsArray objectAtIndex:i]objectForKey:#"Word"];
NSString *firstLetter = [[word substringToIndex:1]uppercaseString];
if ([buffer objectForKey:firstLetter]) {
[(NSMutableArray *)[buffer objectForKey:firstLetter]addObject:keyValue];
}
else {
NSMutableArray *mutableArray = [[NSMutableArray alloc]initWithObjects:keyValue, nil];
[buffer setObject:mutableArray forKey:firstLetter];
}
}
NSArray *bufferKeys = [buffer allKeys];
for (int j; j<bufferKeys.count; j++) {
NSString *bufferkey = [bufferKeys objectAtIndex:j];
[(NSMutableArray *)[buffer objectForKey:bufferkey]sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
NSDictionary *result = [NSDictionary dictionaryWithDictionary:buffer];
return result;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [keys count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *key = [_sortedKeys objectAtIndex:section];
NSArray *wordsForSection = [self.alphabetizedWords objectForKey:key];
return [wordsForSection count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *key = [_sortedKeys objectAtIndex:[indexPath section]];
NSArray *wordsForSection = [self.alphabetizedWords objectForKey:key];
NSString *word = [[wordsForSection objectAtIndex:[indexPath row]]objectForKey:#"Word"];
[cell.textLabel setText:word];
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *key = [_sortedKeys objectAtIndex:section];
return key;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"showDetail" sender:cell];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
detailViewController *destViewController = segue.destinationViewController;
NSString *key = [_sortedKeys objectAtIndex:[indexPath section]];
NSArray *wordsForSection = [self.alphabetizedWords objectForKey:key];
NSString *word = [[wordsForSection objectAtIndex:[indexPath row]]objectForKey:#"Word"];
destViewController.word = word;
destViewController.definition = [[wordsForSection objectAtIndex:[indexPath row] ]objectForKey:#"Definition"];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *path = [[NSBundle mainBundle]pathForResource:#"words" ofType:#"plist"];
NSArray *wordsDictionary = [NSArray arrayWithContentsOfFile:path];
self.words = wordsDictionary;
self.alphabetizedWords = [self alphabetizedWords:self.words];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
self.keys = [self.alphabetizedWords allKeys];
self.sortedKeys = [keys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You are creating an array of dictionaries. Dictionaries don't support the compare method. You therefore can't use a selector based sort. You need to use a different sort method, like sortUsingComparator, or a predicate. (There are lots of different ways to sort arrays.)
If you just have to reverse the position of element of array you could use following
NSArray *wordArray = [[NSArray alloc] initWithObjects:#"Brian",#"Job",#"Bob",#"Ben",#"Robert", nil];
wordArray = [[wordArray reverseObjectEnumerator] allObjects];
Your output will be : Robert, Ben, Bob, Job, Brian.
Thought I was on a roll and then fell flat on my face again.
After inserting my code to sort plist data into sections, my tableview is showing blank.
For note, I have reconnected dataSource and delegate, and know the prepareForSegue is not right - once I have the cells showing I will be updating that (was working without sections).
It's obviously me but I can't see the error and it is building fine.
Ps: I am aware it is not optimised for memory management. Once tableview is working I shall be declaring a keys property and sorting them into that, etc.
Also, the reason there is no NSLog statements is that my XCODE will not output anything in the console.
Thanks
#import "RCViewController.h"
#import "detailView.h"
#interface RCViewController ()
#end
#implementation RCViewController
#synthesize orderedPlistWords, tableView;
#synthesize alphabeticallySortedWords;
static NSString *CellIdentifier = #"Cell Identifier";
-(NSDictionary *)alphabeticallySortedWords:(NSArray *)wordsArray {
NSMutableDictionary *buffer = [[NSMutableDictionary alloc]init];
for (NSDictionary *dict in orderedPlistWords) {
NSString *word = [dict objectForKey:#"Word"];
NSString *firstLetter = [[word substringToIndex:1]uppercaseString];
if ([buffer objectForKey:firstLetter]) {
[(NSMutableArray *)[buffer objectForKey:firstLetter]addObject:dict];
}
else {
NSMutableArray *mutableArray = [[NSMutableArray alloc]initWithObjects:dict, nil];
[buffer setObject:mutableArray forKey:firstLetter];
}
}
NSArray *keys = [buffer allKeys];
for (int j; j<keys.count; j++) {
NSString *key = [keys objectAtIndex:j];
[(NSMutableArray *)[buffer objectForKey:key]sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
NSDictionary *result = [NSDictionary dictionaryWithDictionary:buffer];
return result;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSArray *keys = [self.alphabeticallySortedWords allKeys];
return [keys count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSArray *unsortedKeys = [self.alphabeticallySortedWords allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:[indexPath section]];
NSArray *wordsForSection = [[self.alphabeticallySortedWords objectForKey:key]objectForKey:#"Word"];
NSString *word = [wordsForSection objectAtIndex:[indexPath row]];
[cell.textLabel setText:word];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *unsortedKeys = [self.alphabeticallySortedWords allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:section];
NSArray *wordsForSection = [[self.alphabeticallySortedWords objectForKey:key]objectForKey:#"Word"];
return [wordsForSection count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"showDetail" sender:cell];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSArray *keys = [[self.alphabeticallySortedWords allKeys]sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [keys objectAtIndex:section];
return key;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
detailView *destViewController = segue.destinationViewController;
destViewController.word = [[self.orderedPlistWords objectAtIndex:indexPath.row]valueForKey:#"Word"];
destViewController.definition = [[self.orderedPlistWords objectAtIndex:indexPath.row]valueForKey:#"Definition"];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *plistPath = [[NSBundle mainBundle]pathForResource:#"words" ofType:#"plist"];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"Word" ascending:YES selector:#selector(caseInsensitiveCompare:)];
NSMutableArray *plistWords = [[NSMutableArray alloc]initWithContentsOfFile:plistPath];
self.orderedPlistWords = [plistWords sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
<?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>Word</key>
<string>Pitch</string>
<key>Definition</key>
<string>Ground players play on</string>
</dict>
<dict>
<key>Word</key>
<string>Goal</string>
<key>Definition</key>
<string>Point awarded when ball crosses goal line</string>
</dict>
<dict>
<key>Word</key>
<string>Yellow Card</string>
<key>Definition</key>
<string>Penalise player for foul</string>
</dict>
</array>
</plist>
You have a property, alphabeticallySortedWords that your UITableViewDataSource methods reference, but that you never populate. You have a similarly named method, alphabeticallySortedWords, but that takes an array parameter.
Whenever you have problems like this. Put breakpoints in numberOfRowsInSection and numberOfSectionsInTableView. That will confirm that these methods are getting called at all (i.e. make sure your scene's base class was set properly, make sure that you've set the data source for the table view property, etc.). In this case, if you had done that, you would have immediately discovered that alphabeticallySortedWords was nil.
By the way, there are other bugs here, too:
In numberOfRowsInSection, you have a line that says:
NSArray *wordsForSection = [[self.alphabeticallySortedWords objectForKey:key] objectForKey:#"Word"];
It should be:
NSArray *wordsForSection = [self.alphabeticallySortedWords objectForKey:key];
Likewise in cellForRowAtIndexPath you have lines that say:
NSArray *wordsForSection = [[self.alphabeticallySortedWords objectForKey:key] objectForKey:#"Word"];
NSString *word = [wordsForSection objectAtIndex:[indexPath row]];
They should be:
NSArray *wordsForSection = [self.alphabeticallySortedWords objectForKey:key];
NSString *word = [[wordsForSection objectAtIndex:[indexPath row]] objectForKey:#"Word"];
In both of those situations, you are extracting Word at the wrong time.
I can't seem to find too much on this. I'm currently trying to create a swipable delete button that will delete the row that is swiped, and if that row is now empty from the section header it will delete the section header as well. For example, "Bread" is swiped to delete, and there is nothing else under the section header "B". Then this will delete both Bread, and the "B" section header. My code is below.
#interface ChoicesTableViewController () <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UITableView *myTableView;
#property (strong, nonatomic) NSMutableArray *items;
#property (strong, nonatomic) NSMutableDictionary *alphabetizedItems;
#end
#implementation ChoicesTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
self.items = [[NSMutableArray alloc] init];
[self.items addObject:#"Apples"];
[self.items addObject:#"Bread"];
self.alphabetizedItems = [self alphabetizeItems:self.items];
}
//Segue if the item is tapped
//- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
//{
// MyDataChoices *currentRow = self.arrayNames[indexPath.row];
// self.mySelectedCell = currentRow.myNameChoices;
//
// [self performSegueWithIdentifier:#"unwindSegueAction" sender:self];
//
//}
////unwind segue from add choice
- (IBAction)unwindSegueToChoices:(UIStoryboardSegue *)segue
{
AddChoiceViewController *sourceVC = segue.sourceViewController;
NSString *myNewItem = sourceVC.myTextField.text;
//NSString *myFinalString = [[myNewItem substringToIndex:1] capitalizedString];
NSString *stringCapitalized = [myNewItem capitalizedString];
[self.items addObject:stringCapitalized];
self.alphabetizedItems = [self alphabetizeItems:self.items];
//[self.arrayNames addObjectsFromArray:#[[MyDataChoices itemWithNewName:stringCapitalized]]];
[self.tableView reloadData];
}
//titles for talble view
#pragma mark Helper Methods
- (NSMutableDictionary *)alphabetizeItems:(NSArray *)items {
NSMutableDictionary *buffer = [[NSMutableDictionary alloc] init];
// Put Fruits in Sections
for (int i = 0; i < [items count]; i++) {
NSString *fruit = [items objectAtIndex:i];
NSString *firstLetter = [[fruit substringToIndex:1] uppercaseString];
if ([buffer objectForKey:firstLetter]) {
[(NSMutableArray *)[buffer objectForKey:firstLetter] addObject:fruit];
} else {
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:fruit, nil];
[buffer setObject:mutableArray forKey:firstLetter];
}
}
// Sort Fruits
NSArray *keys = [buffer allKeys];
for (int j = 0; j < [keys count]; j++) {
NSString *key = [keys objectAtIndex:j];
[(NSMutableArray *)[buffer objectForKey:key] sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:buffer];
return result;
}
#pragma mark title indexing
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSArray *keys = [[self.alphabetizedItems allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [keys objectAtIndex:section];
return key;
}
# pragma mark main table view
-(NSInteger) numberOfSectionsInTableView:(UITableView *) tableView
{
NSArray *keys = [self.alphabetizedItems allKeys];
return [keys count];
}
-(NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger)section
{
//return self.arrayNames.count;
NSArray *unsortedKeys = [self.alphabetizedItems allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:section];
NSArray *fruitsForSection = [self.alphabetizedItems objectForKey:key];
return [fruitsForSection count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//MyDataChoices *currentRow = self.arrayNames[indexPath.row];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"mainCell2" forIndexPath:indexPath];
//cell.textLabel.text = currentRow.myNameChoices;
NSArray *unsortedKeys = [self.alphabetizedItems allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:[indexPath section]];
NSArray *fruitsForSection = [self.alphabetizedItems objectForKey:key];
NSString *fruit = [fruitsForSection objectAtIndex:[indexPath row]];
[cell.textLabel setText:fruit];
return cell;
}
# pragma Mark delete slide button
//Delete Swipe Button
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
int index = indexPath.row;
//[self.items removeObjectAtIndex:index];
[self.alphabetizedItems removeObjectForKey:indexPath];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The basic approach is to see how many rows are in the section for the row being deleted. If the section has two or more rows, simply delete the row as you are doing now. If the section only has one row (the one being deleted), then remove the section from the data model and then delete the section from the table instead of deleting the row.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSArray *unsortedKeys = [self.alphabetizedItems allKeys];
NSArray *sortedKeys = [unsortedKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *key = [sortedKeys objectAtIndex:[indexPath section]];
NSArray *fruitsForSection = [self.alphabetizedItems objectForKey:key];
if (fruitsForSection.count == 1) {
// Delete the whole section
[self.alphabetizedItems removeObjectForKey:key];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
} else {
// Delete the row from the data source
NSInteger index = indexPath.row;
//[self.items removeObjectAtIndex:index];
[self.alphabetizedItems removeObjectForKey:indexPath];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
I have a plist with contacts: the root is an array, items 0-150 are dictionaries, each dictionary is a single contact with a "name", "number", and "email" string.
The code below sorts the contacts alphabetically into sections based upon the "name" string. Then uses the inner array to populate the cells for each section. I then pass the name from the inner array to my detail view.
However, I can not figure out how to pass the correct number and email for each contact into the detail view. I've been working on this issue for a long while and can not find a solution.
#interface ContactsViewController ()
-(void)configureSectionData;
#end
#implementation ContactsViewController
#synthesize tableData;
#synthesize collation;
#synthesize outerArray;
#synthesize indexTitlesArray, namesDictionary;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - Table view methods
-(void)configureSectionData {
NSUInteger sectionTitlesCount = [collation.sectionTitles count];
self.outerArray = [NSMutableArray arrayWithCapacity:sectionTitlesCount];
for (NSUInteger index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [NSMutableArray array];
[self.outerArray addObject:array];
}
for (NSString *nameString in tableData)
{
NSInteger sectionNumber = [collation sectionForObject:nameString collationStringSelector:#selector(lowercaseString)];
NSMutableArray *sectionNames = [outerArray objectAtIndex:sectionNumber];
[sectionNames addObject:nameString];
}
for (NSUInteger index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *namesForSection = [outerArray objectAtIndex:index];
NSArray *sortedNamesForSection = [collation sortedArrayFromArray:namesForSection collationStringSelector:#selector(lowercaseString)];
[self.outerArray replaceObjectAtIndex:index withObject:sortedNamesForSection];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.collation.sectionTitles count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *theLetter = [self.collation.sectionTitles objectAtIndex:section];
if (![theLetter isEqualToString:#"#"]) {
NSString *titleString = [NSString stringWithFormat:#"%#", theLetter];
return titleString;
}
return nil;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.collation.sectionTitles;
}
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.collation sectionForSectionIndexTitleAtIndex:index];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *innerArray = [self.outerArray objectAtIndex:section];
return [innerArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *theName = [innerArray objectAtIndex:indexPath.row];
cell.textLabel.text = theName;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainiPhoneStoryboard" bundle:nil];
DetailViewController *detailView = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *tmpname = [innerArray objectAtIndex:indexPath.row];
detailView.lblname = tmpname;
[self presentViewController:detailView animated:YES completion:nil];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.namesDictionary = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"contacts" ofType:#"plist"]];
self.tableData = [namesDictionary valueForKey:#"name"];
self.collation = [UILocalizedIndexedCollation currentCollation];
[self configureSectionData];
}
Since you're populating your table from an array of just the names from your plist, you'll have to search that array using the name to find the dictionary that it belongs to, so you can pass that to the detail view controller (you would need to create a property in your detail view controller, passedInDictionary in my example):
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainiPhoneStoryboard" bundle:nil];
DetailViewController *detailView = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *tmpname = [innerArray objectAtIndex:indexPath.row];
NSInteger indx = [self.namesDictionary indexOfObjectPassingTest:^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
return [dict[#"name"] isEqualToString:tmpname];
}];
NSDictionary *dict = self.namesDictionary[indx];
detailView.passedInDictionary = dict;
[self presentViewController:detailView animated:YES completion:nil];
}
I load data from plist to uitableview like this:
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [[documentPaths lastObject] stringByAppendingPathComponent:#"data.plist"];
NSMutableDictionary *resultDic = [[NSMutableDictionary alloc] init];
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSDictionary *myDict = [NSDictionary dictionaryWithContentsOfFile:path];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"purpleKey"])
{
NSArray *purple = [myDict objectForKey:#"Purple"];
[resultArray addObject:#"Purple"];
[resultDic setValue:purple forKey:#"Purple"];
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"orangeKey"])
{
NSArray *orange = [myDict objectForKey:#"Orange"];
[resultArray addObject:#"Orange"];
[resultDic setValue:orange forKey:#"Orange"];
}
self.tableData = resultDic;
self.sectionsTitle = resultArray;
}
titleForHeaderInSection
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionsTitle objectAtIndex:section];
}
my plist structure
My question is:
How can I manually set title for Purple header and Orange header without to changing names in plist file?
like this: Purple = Category 1, Orange = Category 2
EDIT
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return sectionsTitle.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionsTitle objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int num = [[tableData objectForKey:[sectionsTitle objectAtIndex:section]] count];
if (num > 3) {
num = 3;
}
return num;
}
// Customize the appearance of table view cells.
- (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];
}
NSDictionary *dict = [[tableData objectForKey:[sectionsTitle objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.numberOfLines = 1;
cell.textLabel.font = [UIFont systemFontOfSize:11];
cell.textLabel.text = [NSString stringWithFormat:#"%# - %#", [dict objectForKey:#"Name"], [dict objectForKey:#"Address"]];
if ([dict objectForKey:#"Address"] == (NULL)) {
//do nothing
}
return cell;
}
From the look of your code, the section headers are coming from resultsArray, which you are populating with the constant strings Orange and Purple.
You can just put different constant strings into that array, unless I'm missing something.
So, instead of
[resultArray addObject:#"Orange"];
Use
[resultArray addObject:#"Category 1"];