NSSortDescriptor 对可能为 nil 的属性进行排序
NSSortDescriptor sorting on properties that could be nil
我有一组报告它们距离的信标,我正在一个项目中工作,该项目具有我无法更改的既定架构,否则我可能可以选择不同的方法。
存在报告其平均距离的信标对象数组。现有代码根据平均距离对信标数组进行排序,存储在名为 _averageDistance
的 属性 中。一切正常,直到离线信标报告 nil _averageDistance
表明它不可用。
当前代码如下:
NSSortDescriptor* sortOnDistance = [NSSortDescriptor sortDescriptorWithKey:@"averageDistance" ascending:YES];
NSArray* sortDescriptors = [NSArray arrayWithObject:sortOnDistance];
NSArray* sortedBeacons = [allBeacons sortedArrayUsingDescriptors:sortDescriptors];
BOOL sameBeacon = NO;
if(![[sortedBeacons firstObject] isEqual:_closestBeacon]){
_closestBeacon = (PTBeacon*)[sortedBeacons firstObject];
}
else {
sameBeacon = YES;
}
有没有办法控制在对 NSArray 进行排序时处理 nil 值的方式?谢谢!
我会编写自定义 NSSortDescriptor
来处理您认为合适的 nil 值:
NSSortDescriptor* sortOnDistance = [NSSortDescriptor sortDescriptorWithKey:@"averageDistance"
ascending:YES
comparator:^NSComparisonResult(id obj1, id obj2) {
if(obj1 == nil){
//customize here
return NSOrderedDescending;
}else if(obj2 == nil){
return NSOrderedAscending;
}else{
return [obj1 compare:obj2];}
}];
您可以使用不同的排序方法将不可用的信标强制排到最后:
[allBeacons sortedArrayUsingComparator:^(PTBeacon * firstBeacon, PTBeacon * secondBeacon){
if( ![firstBeacon averageDistance] ){
return (NSComparisonResult)NSOrderedAscending;
}
else {
return [[firstBeacon averageDistance] compare:[secondBeacon averageDistance]];
}
}];
这使得 averageDistance
为 nil
的任何信标比任何其他信标都大,这与当前发生的情况相反。不可用的信标将最终(在它们之间以任意顺序)超过排序数组中的任何其他信标。
或者您可以在排序前过滤数组:
NSPredicate * availabilityPredicate = [NSPredicate predicateWithFormat:@"averageDistance != NIL"];
NSArray * allAvailableBeacons = [allBeacons filteredArrayUsingPredicate:availabilityPredicate];
这将导致 allAvailableBeacons
仅包含 averageDistance
不是 nil
的信标。然后您对该数组而不是原始数组进行排序。
我有一组报告它们距离的信标,我正在一个项目中工作,该项目具有我无法更改的既定架构,否则我可能可以选择不同的方法。
存在报告其平均距离的信标对象数组。现有代码根据平均距离对信标数组进行排序,存储在名为 _averageDistance
的 属性 中。一切正常,直到离线信标报告 nil _averageDistance
表明它不可用。
当前代码如下:
NSSortDescriptor* sortOnDistance = [NSSortDescriptor sortDescriptorWithKey:@"averageDistance" ascending:YES];
NSArray* sortDescriptors = [NSArray arrayWithObject:sortOnDistance];
NSArray* sortedBeacons = [allBeacons sortedArrayUsingDescriptors:sortDescriptors];
BOOL sameBeacon = NO;
if(![[sortedBeacons firstObject] isEqual:_closestBeacon]){
_closestBeacon = (PTBeacon*)[sortedBeacons firstObject];
}
else {
sameBeacon = YES;
}
有没有办法控制在对 NSArray 进行排序时处理 nil 值的方式?谢谢!
我会编写自定义 NSSortDescriptor
来处理您认为合适的 nil 值:
NSSortDescriptor* sortOnDistance = [NSSortDescriptor sortDescriptorWithKey:@"averageDistance"
ascending:YES
comparator:^NSComparisonResult(id obj1, id obj2) {
if(obj1 == nil){
//customize here
return NSOrderedDescending;
}else if(obj2 == nil){
return NSOrderedAscending;
}else{
return [obj1 compare:obj2];}
}];
您可以使用不同的排序方法将不可用的信标强制排到最后:
[allBeacons sortedArrayUsingComparator:^(PTBeacon * firstBeacon, PTBeacon * secondBeacon){
if( ![firstBeacon averageDistance] ){
return (NSComparisonResult)NSOrderedAscending;
}
else {
return [[firstBeacon averageDistance] compare:[secondBeacon averageDistance]];
}
}];
这使得 averageDistance
为 nil
的任何信标比任何其他信标都大,这与当前发生的情况相反。不可用的信标将最终(在它们之间以任意顺序)超过排序数组中的任何其他信标。
或者您可以在排序前过滤数组:
NSPredicate * availabilityPredicate = [NSPredicate predicateWithFormat:@"averageDistance != NIL"];
NSArray * allAvailableBeacons = [allBeacons filteredArrayUsingPredicate:availabilityPredicate];
这将导致 allAvailableBeacons
仅包含 averageDistance
不是 nil
的信标。然后您对该数组而不是原始数组进行排序。