iOS8中的NSMutableDictionary顺序不同(与iOS7相反)

时间:2014-10-14 21:14:08

标签: ios objective-c nsmutablearray nsmutabledictionary

在过去几年(iOS8 / XCode 6之前),此代码按照

的顺序生成了一个表
  • 设备名称
  • 燃烧气体分析
  • 安全检查
  • 设备检查
  • 调查结果

现在在iOS8 / XCode 6中翻转NSMutableDictionary中两个NSMutableArray的顺序,因此输出

  • 燃烧气体分析
  • 安全检查
  • 设备检查
  • 调查结果
  • 设备名称

为什么???

#import "svServiceVC.h"
#import "SingletonID.h"
#import "escgasDatabase.h"
#import "FMDBDataAccess.h"

@interface svServiceVC ()
@end

@implementation svServiceVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.theTable.delegate = self;
    self.theTable.dataSource =self;
}

- (void)viewWillAppear:(BOOL)animated
{
    [self buildTableData];
    [_theTable reloadData];
}

- (void)buildTableData
{
    anApplianceNamed = 0;
    generalInspectationDone = 0;
    _appliancesDict = [[NSMutableDictionary alloc] init];
    [_appliancesDict setValue:[[NSMutableArray alloc] init] forKey:@"Appliances"];
    [_appliancesDict setValue:[[NSMutableArray alloc] init] forKey:@"Inspection"];

    // snip


    [[_appliancesDict objectForKey:@"Appliances"] addObject:appString1];

    [[_appliancesDict objectForKey:@"Inspection"] addObject:@"Combustion gas analysis"];

    [[_appliancesDict objectForKey:@"Inspection"] addObject:@"Safety checks"];

    [[_appliancesDict objectForKey:@"Inspection"] addObject:@"Appliance checks"];

    [[_appliancesDict objectForKey:@"Inspection"] addObject:@"Findings & Completion"];

    generalInspectationDone = 1;
}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [_appliancesDict count];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[_appliancesDict valueForKey:[[_appliancesDict allKeys] objectAtIndex:section]] count];
}


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

    UITableViewCell *cell;
    NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];

    if ( 6 <= [[versionCompatibility objectAtIndex:0] intValue] )
    {
        // iOS6 is installed
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    }
    else
    {
        // iOS5 is installed
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier ];
    }


    NSString *appTitle = [[_appliancesDict valueForKey:[[_appliancesDict allKeys] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];

    cell.textLabel.text = appTitle;

    if (indexPath.section==0)
    {
        // The appliance cells

        if ([cell.textLabel.text hasPrefix:@"Appliance"])
        {
            cell.textLabel.textColor = [UIColor lightGrayColor];
        }
        else
        {
            cell.textLabel.textColor = [UIColor blackColor];
        }



    }
    else
    {

        // The inspection rows

        if (indexPath.row==0)
        {
            //
            if (gasInspection==0)
            {
                cell.textLabel.textColor = [UIColor lightGrayColor];
            }
            else
            {
                cell.textLabel.textColor = [UIColor blackColor];
            }


        }
        else if (indexPath.row==1)
        {
            // * Gas inpsection

            if (safetyChecks==0)
            {
                cell.textLabel.textColor = [UIColor lightGrayColor];
            }
            else
            {
                cell.textLabel.textColor = [UIColor blackColor];
            }


        }
        else if (indexPath.row==2)
        {
            // * Gas inpsection

            if (applianceChecks==0)
            {
                cell.textLabel.textColor = [UIColor lightGrayColor];
            }
            else
            {
                cell.textLabel.textColor = [UIColor blackColor];
            }


        }
        else if (indexPath.row==3)
        {

            if (generalInspectationDone==0)
            {
                //cell.textLabel.textColor = [UIColor lightGrayColor];
                cell.textLabel.textColor = [UIColor blackColor];
            }
            else
            {
                cell.textLabel.textColor = [UIColor blackColor];
            }

        }


    }

    return cell;
}


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"didSelectRowAtIndexPath:indexpath %li %li",(long)indexPath.section, (long)indexPath.row);

    switch (indexPath.section)
    {
        case 0:

            // Appliances
            [SingletonID sharedSingleton].appliance = @"_1";


            [self performSegueWithIdentifier:@"svApplianceSegue" sender:self];
            break;

        case 1:


            switch (indexPath.row){

            case 0:
                [self goGasAnalysis];
                break;

            case 1:
                [self goSafety];
                break;

            case 2:
                [self goChecks];
                break;

            case 3:
                [self goComplete];
                break;

            default:
                break;

        }


    }

}

3 个答案:

答案 0 :(得分:3)

字典无序。这是一个实现细节。答案为&#34;为什么?&#34;是Apple改变了实施方式。因为他们知道好的代码永远不会依赖于订单,所以他们可以自由地这样做。

如果您想按特定顺序使用密钥,可以保留一个单独的数组,并按照您喜欢的顺序存储密钥。

答案 1 :(得分:3)

NSString *appTitle = [[_appliancesDict valueForKey:[[_appliancesDict allKeys] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];

您正在使用allKeys获取&#39;部分的列表&#39;,在这种情况下&#34; Appliances&#34;和&#34;检查&#34;。这里的问题是Dictionary不强制对其键进行排序。您可以在NSDictionary's allKeys的文档中看到这一点,因为它明确说明了这一事实。

  

allKeys

     

返回一个包含字典键的新数组。

     

返回值:包含字典键的新数组,如果字典没有条目,则为空数组。

     

讨论:未定义数组中元素的顺序。

iOS 8中NSDictionary的实现似乎发生了一些变化,影响了密钥的内部排序。因为API从一开始就不能保证固定的顺序,所以Apple可以做到这一点。

答案 2 :(得分:2)

文档说:

  

allKeys返回一个包含字典键的新数组。

     

- (NSArray *)allKeys

     

返回值

     

包含字典键的新数组,如果字典没有条目,则为空数组。

     

讨论

     

未定义数组中元素的顺序。

(强调补充)

因此允许NSDictionary以任何顺序返回密钥。从技术上讲,它可以在您每次拨打allKeys时随机化订单并仍然履行其合同义务。

订单更改无需具体原因。如果您想要确定性排序,请使用-keysSortedByValueUsingSelector:(或通过比较器),或自己对allKeys数组进行排序。