indexOfObject:inSortedRange:options:usingComparator:
にNSBinarySearchingInsertionIndex
を指定すれば、追加するべきIndexが取得できる。
NSArray *sourceData = @[
@{@"id": @"A", @"createdAt": @1234533333},
@{@"id": @"B", @"createdAt": @1234599999},
@{@"id": @"C", @"createdAt": @1234511111},
@{@"id": @"D", @"createdAt": @1234522222},
@{@"id": @"E", @"createdAt": @1234599999},
];
// Sort descritors
NSSortDescriptor *createdAtSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO];
NSSortDescriptor *idSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"id" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
// 並び替え(作成日降順、ID昇順)
NSMutableArray *objects = [sourceData sortedArrayUsingDescriptors:@[createdAtSortDescriptor, idSortDescriptor]].mutableCopy;
/*! ->
@[
@{@"id": @"B", @"createdAt": @1234599999},
@{@"id": @"E", @"createdAt": @1234599999},
@{@"id": @"A", @"createdAt": @1234533333},
@{@"id": @"D", @"createdAt": @1234522222},
@{@"id": @"C", @"createdAt": @1234511111},
];
*/
// 新規データ
NSDictionary *newObject = @{@"id": @"F", @"createdAt": @1234544444};
// NSBinarySearchingFirstEqualも合わせて指定すると最初にマッチしたIndexを返す
NSUInteger searchOptions = NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual;
// 追加するデータのIndexの取得
NSInteger newIndex = [objects indexOfObject:newObject inSortedRange:NSMakeRange(0, objects.count) options:searchOptions usingComparator:^NSComparisonResult(NSDictionary *d1, NSDictionary *d2) {
if (![d1[@"createdAt"] isEqualToNumber:d2[@"createdAt"]]) {
return [d2[@"createdAt"] compare:d1[@"createdAt"]];
}
return [d1[@"id"] localizedCaseInsensitiveCompare:d2[@"id"]];
}];
// -> 2
[objects insertObject:newObject atIndex:newIndex];
/*! ->
@[
@{@"id": @"B", @"createdAt": @1234599999},
@{@"id": @"E", @"createdAt": @1234599999},
@{@"id": @"F", @"createdAt": @1234544444},
@{@"id": @"A", @"createdAt": @1234533333},
@{@"id": @"D", @"createdAt": @1234522222},
@{@"id": @"C", @"createdAt": @1234511111},
];
*/