Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting NSDictionary key by index?

Is it possible to get a dictionary key by index?

I'm trying to use a dictionary for the datasource of a picker view and want to access it in following delegate method:

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
if (component == 0){
   return  [NSString stringWithFormat:@"%@",[myDict // how to get the key]];
}

EDIT--

myDict is something like:

Item 1

  • sub item 1
  • sub item 2

Item 2

  • sub item 1
  • sub item 2

I want to use myDict as the datasource for a picker view that has 2 sections:

section 0 = myDict keys (Item 1, Item 2)

section 1 = corresponding myDict values for selected section 0 row (sub item 1, sub item 2)

like image 305
Sam Luther Avatar asked May 14 '14 14:05

Sam Luther


3 Answers

This will give you randomly ordered keys

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row    forComponent:(NSInteger)component{
    if (component == 0){
        return  [NSString stringWithFormat:@"%@",[myDict allKeys][row]];
    }
}
like image 132
Hao Avatar answered Sep 30 '22 17:09

Hao


Since NSDictionary is an unordered associative container, it has no concept of indexing. Its keys are ordered arbitrarily, and that order can change in the future.

You can get an NSArray of keys from the dictionary, and apply indexing to it:

NSArray *keys = [myDict allKeys]; // Warning: this order may change.

However, this indexing scheme would remain consistent only as long as the dictionary remains unchanged: for example, if you use NSMutableDictionary, adding an extra key may change the ordering of the existing keys. This leads to extremely hard-to-debug problems.

A better approach would be to place the items for your picker into an ordered container, such as NSArray. Create a special class for the picker items, for example

@interface MyPickerItem : NSObject
@property (readwrite, nonatomic) NSString *item1;
@property (readwrite, nonatomic) NSString *item2;
@end

create an NSArray of such MyPickerItem objects from your dictionary, order them the way you want them to appear in the picker view (say, alphabetically by item1, then by item2) and use NSArray as the data source for your picker view:

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    MyPickerItem *p = myArray[row];
    switch (component) {
        case 0: return p.item1;
        case 1: return p.item2;
    }
    return @"<-ERROR->";
}
like image 33
Sergey Kalinichenko Avatar answered Sep 30 '22 19:09

Sergey Kalinichenko


No, as a dictionary doesn't have order.

You'll need to provide an array of keys, which will give you your order, in addition to the dictionary.

@interface MyClass ()
@property NSMutableArray *keysArray;     // Don't forget to allocate this in an init method
@end

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component
{
    if (component == 0){
        NSString *key = self.keysArray[row];
        return self.myDict[key];    // I assume you just want to return the value
    }
    ...
like image 21
trojanfoe Avatar answered Sep 30 '22 19:09

trojanfoe