【问题标题】:Best way to grab an array of dictionaries from a plist and create sections based on the values for a key从 plist 中获取字典数组并根据键的值创建部分的最佳方法
【发布时间】:2010-11-18 19:59:04
【问题描述】:

我有一个 plist,其中包含一个带有字典集合的数组。数组中的字典用于创建一个相当复杂的表格视图,每个单元格中有 2 个图像和 2 行文本。我想根据与“MainText”键对应的值的第一个字母在表格视图中创建部分。

这里是 plist 格式。在此示例中,应该有 2 个部分,一个用于“MainText”字符串以“A”开头的字典,一个用于“MainText”字符串以“B”开头的 2 个字典。

<dict>
<key>Rows</key>
<array>
    <dict>
        <key>MainText</key>
        <string>A sometext</string>
        <key>SecondaryText</key>
        <string>somemoretext</string>
        <key>PrimaryIcon</key>
        <string>firsticon.png</string>
        <key>SecondaryIcon</key>
        <string>secondicon.png</string>
    </dict>
    <dict>
        <key>MainText</key>
        <string>B sometext</string>
        <key>SecondaryText</key>
        <string>somemoretext</string>
        <key>PrimaryIcon</key>
        <string>firsticon.png</string>
        <key>SecondaryIcon</key>
        <string>secondicon.png</string>
    </dict>
            <dict>
        <key>MainText</key>
        <string>B moreTextStartingWith"B"</string>
        <key>SecondaryText</key>
        <string>somemoretext</string>
        <key>PrimaryIcon</key>
        <string>firsticon.png</string>
        <key>SecondaryIcon</key>
        <string>secondicon.png</string>
    </dict>
</array>

我已经编写了代码,用于从“MainText”键处的字符串中提取第一个字母,对它们进行排序并创建节标题。我还有用于在每个部分中设置正确行数的代码。这是我在 viewDidLoad 方法中纠结的一些代码。

//Create an array sorted by the strings in "MainText" of the AppDelegate.data
    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"MainText" ascending:YES] autorelease];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    NSArray *sortedArray;
    sortedArray = [[AppDelegate.data objectForKey:@"Rows"] sortedArrayUsingDescriptors:sortDescriptors];


//Now set tableDataSource equal to sortedArray
    self.tableDataSource = sortedArray;

//Create a set of the first letters used by the strings in MainText
    NSMutableSet *firstCharacters = [NSMutableSet setWithCapacity:0];
    for( NSString *string in [tableDataSource valueForKey:@"MainText"] )
        [firstCharacters addObject:[string substringToIndex:1]];

//Create a sorted array of first letters used by strings in MainText
    self.arrayOfInitialLetters = [[firstCharacters allObjects] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];

//Create an array of the MainText of each item in tableDataSource   
    NSMutableArray * mainTextArray = [tableDataSource valueForKey:@"MainText"];

我应该如何在 cellForRowAtIndexPath 方法中获取正确的行?目前,每个部分只显示从第一个开始的相同单元格。我需要以某种方式在我的数据源中定义有不同的部分。感谢您的帮助,这是一场真正的斗争!

【问题讨论】:

  • 在您的 plist 中,我认为它应该以第二个结束 读取,并且 应该在末尾?...
  • 是的。它一定是在副本中丢失了。我在上面更正了。

标签: iphone arrays uitableview dictionary


【解决方案1】:

我终于得到了这个工作。这是我的 viewDidLoad 方法的代码。这可能不是获得我的结果的最干净的方法,但效果很好!不过,我欢迎任何建议。

- (void)viewDidLoad {
[super viewDidLoad];

// Load the UICustomTabViewController
    UICustomTabViewController *tvController = [[UICustomTabViewController alloc]
         initWithNibName:@"TabViewController" bundle:nil];
    self.tabViewController = tvController;
    [tvController release];

    YourAppDelegate *AppDelegate = (YourAppDelegate *)[[UIApplication
         sharedApplication] delegate];


// Create an array sorted by CommonName of the AppDelegate.data
    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"CommonName" ascending:YES] autorelease];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    NSArray *sortedArray;
    sortedArray = [[AppDelegate.data objectForKey:@"Rows"] sortedArrayUsingDescriptors:sortDescriptors];

// Now set tableDataSource equal to sortedArray
    self.tableDataSource = sortedArray;

// Create a set of the first letters used by the strings in CommonName and sort them
    NSMutableSet *firstCharacters = [NSMutableSet setWithCapacity:0];
    for( NSString *string in [tableDataSource valueForKey:@"CommonName"] )
        [firstCharacters addObject:[string substringToIndex:1]];
        self.arrayOfInitialLetters = [[firstCharacters allObjects]
        sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];

    self.sectionedDictionaryByFirstLetter = [NSMutableDictionary dictionary];           

// All data sorted in sections by initial letter of "CommonName"
    NSDictionary *eachItemList;  //PUTS ALL THE DATA FOR EACH ITEM IN IT'S OWN SECTION
    for (eachItemList in tableDataSource)   //eachElementList is an array with a section for each item
    {
        NSDictionary *aDictionary = [[NSDictionary alloc] initWithDictionary:eachItemList];
        NSString *firstLetterString;
        firstLetterString = [[aDictionary valueForKey:@"CommonName"]substringToIndex:1];

        NSMutableArray *existingArray;

        if (existingArray = [sectionedDictionaryByFirstLetter valueForKey:firstLetterString]) 
        {
            [existingArray addObject:eachItemList];
        } else {
            NSMutableArray *tempArray = [NSMutableArray array];
            [sectionedDictionaryByFirstLetter setObject:tempArray forKey:firstLetterString];
            [tempArray addObject:eachItemList];
        }
        [aDictionary release];
        [eachItemList release];
        NSLog(@"nameIndexesDictionary:%@", sectionedDictionaryByFirstLetter);
    }

这就是我在 cellForRowAtIndexPath 方法中获得正确行的方法

    NSInteger section = [indexPath section];
    NSString *key = [arrayOfInitialLetters objectAtIndex:section];  
    NSArray *nameSection = [sectionedDictionaryByFirstLetter objectForKey:key];
    NSDictionary *dictionary = [nameSection objectAtIndex:indexPath.row];

【讨论】:

    【解决方案2】:

    您的 XML 看起来有问题。好像应该是这样的:

    <dict>
    <key>Rows</key>
    <array>
            <dict>
                    <key>MainText</key>
                    <string>A sometext</string>
                    <key>SecondaryText</key>
                    <string>somemoretext</string>
                    <key>PrimaryIcon</key>
                    <string>firsticon.png</string>
                    <key>SecondaryIcon</key>
                    <string>secondicon.png</string>
            </dict>
            <dict>
                    <key>MainText</key>
                    <string>B sometext</string>
                    <key>SecondaryText</key>
                    <string>somemoretext</string>
                    <key>PrimaryIcon</key>
                    <string>firsticon.png</string>
                    <key>SecondaryIcon</key>
                    <string>secondicon.png</string>
            </dict>
    </array>
    </dict>
    

    您可以为 NSDictionary 创建一个类别,以便您对数据进行排序。像这样的:

    @interface NSDictionary (Sorting) 
    
    -(NSComparisonResult)compareRows:(NSDictionary*)row;
    
    @end
    
    @implementation NSDictionary (Sorting)
    
    -(NSComparisonResult)compareRows:(NSDictionary*)row;
    {
        NSString *rowMainText = [row objectForKey:@"MainText"];
        NSString *selfMainText = [self objectForKey:@"MainText"];
    
        return [selfMaintext localizedCompare:rowMainText];
    }
    @end
    

    然后你可以像这样执行你的排序:

    [rows sortUsingSelector:@selector(compareRow:)];
    

    变量 rows 需要是可变的,因为排序将在内部执行。

    【讨论】:

    • 谢谢。当您发布此答案时,我正在更正plist :) ...我将其复制到此帖子时不知何故搞砸了。在我尝试实现这一点之前,它是根据“MainText”的值将单独的字典分组到部分中,还是只是对它们进行排序?感谢您的帮助,这个一直让我发疯。我也一直在试验 UILocalizedIndexedCollat​​ion 看看它是否可以解决问题。
    • 好的,澄清一下。您是否建议创建一个新的 .h 和 .m 文件对来存储这些 NSComparisonResult 方法?还是应该将它们添加到我的 RootViewController 文件中?我想我不确定您所说的“为 NSDictionary 创建一个类别”究竟是什么意思。非常感谢您的帮助!
    • 这将仅按“MainText”排序,所以现在我可以看到这可能对您没有帮助。如果您愿意,可以将 NSComparisonResult 方法放在它们自己的文件中,例如 NSDictionry+Sorting.h/m,或者您可以在视图控制器类中声明它们——这通常是我所做的。
    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2022-12-02
    • 2013-08-30
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多