Objective-C 中排序與字符串比較看似簡單,實則暗藏陷阱。本文揭示 compare: 系列方法在 nil 接收者下的隱患,並提供數字、字符串、字典、自定義對象四大場景的完整排序代碼模板。
Objective-C 向 nil 發送消息返回 nil(即 0),而 NSOrderedSame == 0。導致:
if ([str1 compare:@"text"] == NSOrderedSame) // str1 為 nil 時條件成立!
後果:邏輯錯誤、UI 異常、數據洩漏等嚴重問題。
修正:
if (str1 != nil && [str1 compare:@"text"] == NSOrderedSame)
- (void)sortNumber {
NSArray *original = @[@"8", @"41", @"32", @"11", @"-1"];
NSComparator cmp = ^(id s1, id s2) {
NSInteger v1 = [s1 integerValue], v2 = [s2 integerValue];
if (v1 > v2) return NSOrderedDescending;
if (v1 < v2) return NSOrderedAscending;
return NSOrderedSame;
};
NSArray *result = [original sortedArrayUsingComparator:cmp];
NSLog(@"%@", result); // (-1, 8, 11, 32, 41)
}
- (void)sortString {
NSArray *arr = @[@"string 1", @"String 21", @"string 12", @"String 11", @"String 02"];
NSStringCompareOptions opts = NSCaseInsensitiveSearch | NSNumericSearch
| NSWidthInsensitiveSearch | NSForcedOrderingSearch;
NSComparator cmp = ^(NSString *s1, NSString *s2) {
return [s1 compare:s2 options:opts range:NSMakeRange(0, s1.length)];
};
NSArray *result = [arr sortedArrayUsingComparator:cmp];
NSLog(@"%@", result);
}
關鍵選項:
NSCaseInsensitiveSearch 忽略大小寫
NSNumericSearch 數字按值比較("2" < "11")
NSWidthInsensitiveSearch 全半角統一
NSForcedOrderingSearch 強制排序(無歧義)
- (void)sortDictionary {
NSMutableArray *arr = [NSMutableArray arrayWithObjects:
@{@"obj0": @"0"}, @{@"obj3": @"3"}, @{@"obj1": @"1"},
@{@"obj2": @"2"}, @{@"obj4": @"4"}, nil];
NSArray *result = [arr sortedArrayUsingComparator:^NSComparisonResult(id d1, id d2) {
NSNumber *k1 = [[d1 allKeys] firstObject];
NSNumber *k2 = [[d2 allKeys] firstObject];
return [k1 compare:k2]; // 升序
// return [k2 compare:k1]; // 降序
}];
NSLog(@"%@", result);
}
- (void)sortCustomObject {
// 假設 SLPerson 有 name、age 屬性
NSSortDescriptor *byAge = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
NSSortDescriptor *byName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
NSArray *result = [persons sortedArrayUsingDescriptors:@[byAge, byName]];
// 先按 age 升序,age 相同則按 name 升序
}
compare: 陷阱代碼下載:https://download.csdn.net/detail/u011883764/7827311