0

I have a plist that contains key and value... let say:

key: alpha_male_body_language
value: Alpha Male Body Language
key: building_attraction
value: Building Attraction
key: fifteen_lessons
value: Fifteen Lessons
key: how_can_it_have_gone_wrong
value: How can It Have Gone Wrong

Here is my implementation of tableview:

#import "BookTitleViewController.h"
#import "BookLessonViewController.h"

@interface BookTitleViewController ()

@end

@implementation BookTitleViewController{
    NSDictionary *bookTitles;
}

@synthesize tableView;
@synthesize bookTitles;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.bookTitles = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"book" ofType:@"plist"]];

}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.

    self.bookTitles = nil;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.bookTitles count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"RecipeCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    }

    NSString *value = [[self.bookTitles allValues] objectAtIndex:indexPath.row];

    //cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
    cell.textLabel.text = value;

    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"ShowBookLesson"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        BookLessonViewController *destViewController = segue.destinationViewController;

        destViewController.bookTitleKey = [[self.bookTitles allKeys] objectAtIndex:indexPath.row];
        destViewController.bookTitleValue = [[self.bookTitles allValues] objectAtIndex:indexPath.row];

        //destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
    }
}

@end

I have two problems using the code above:

  1. The list is not shown in order after reading it from plist. For example, title "How can It have gone wrong" is shown on the first list, knowing the fact that it is listed on the 4th.

  2. I get exception saying:

    -[UINavigationController setBookTitleValue:]: unrecognized selector sent to instance 0x894c230

this is referring to the line:

 destViewController.bookTitleKey = [[self.bookTitles allKeys]     objectAtIndex:indexPath.row];
 destViewController.bookTitleValue = [[self.bookTitles allValues] objectAtIndex:indexPath.row];

(Inside prepareForSegue function).

Please helps me to solve this problem. Thank you and appreciate it!

Mike Mertsock
  • 11,825
  • 7
  • 42
  • 75
Hammy Lin
  • 37
  • 1
  • 6
  • [Abizem's answer below](http://stackoverflow.com/a/17513180/795339) is a good one for your first question. For your second question, your segue's `destinationViewController` may be a `UINavigationController` that *contains* your `BookLessoniewController` as its top level VC. See [my suggested approach](http://stackoverflow.com/a/8041666/795339) for handling this. – Mike Mertsock Jul 07 '13 at 14:53
  • Look at this answer for sorting an NSDictionary and converting to an NSArray. http://stackoverflow.com/questions/4558639/sort-an-nsmutabledictionary – Marcus Adams Jul 07 '13 at 14:58
  • Hi Esker. I still don't get the idea how to solve no 2. Can you point out which part on your "suggested approach" that will solve my problem with no 2? I am still newbie, just learn ios for 3 days... =) – Hammy Lin Jul 07 '13 at 15:25

2 Answers2

2

It looks like your plist is used to generate a dictionary. The keys (and hence the values) in an NSDictionary are not ordered. So the order you get the keys out is not fixed.

So when you are assuming a key and a value to be at a particular position, that is a wrong assumption.

You should use an array as the data source rather than a dictionary.

Abizern
  • 146,289
  • 39
  • 203
  • 257
  • cool insight!! Thanks! Do you have any solution to have objects that has key and value, but sorted in way when an object is inserted for the first time, that would be the first object. Thanks. – Hammy Lin Jul 07 '13 at 15:34
  • 1
    Give it a key that stores it's order – Abizern Jul 07 '13 at 18:21
1

More detail on possible solution to problem 2:

  1. Add UIStoryboardSegue+MMNavigationController.h to your project, found in this Github repo
  2. Import that header file in your view controller's implementation file
  3. Change one line in your implementation of prepareForSegue:sender: like so:
BookLessonViewController *destViewController = segue.topLevelDestinationViewController;

Explanation: if a storyboard segue points points to a destination view controller that is wrapped in a UINavigationController, then the segue's destinationViewController will value will be the navigation controller object. The code referenced here will handle this by checking whether destinationViewController is an instance of the UINavigationController class, and if so, will return its topViewController instead. This is all implemented as a on the UIStoryboardSegue class; categories are a way to add methods or properties to an existing class to extend its functionality without needing to use inheritance, etc.

Mike Mertsock
  • 11,825
  • 7
  • 42
  • 75