在过去几年(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;
}
}
}
答案 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
数组进行排序。