NSTableView列自定义排序异常:无法识别myCompare:方法
解决NSTableView自定义排序(含"不适用"项)的问题
错误原因分析
你遇到的-[__NSCFNumber myCompare:]: unrecognized selector sent to instance错误,核心问题是:故事板中设置的Sort key是myObject(对应自定义对象里的double值属性,实际是NSNumber实例),但你把自定义比较方法myCompare:写在了自定义对象类里,而非NSNumber类。点击排序时,表视图会直接对myObject属性的NSNumber实例调用myCompare:,但NSNumber没有这个方法,因此触发错误。
正确实现步骤
1. 在数据模型类中实现自定义比较方法
假设你的自定义数据模型类叫MyDataObject,内部用value属性存储数值(nil代表"不适用"),在类中实现比较逻辑:
// MyDataObject.h #import <Foundation/Foundation.h> @interface MyDataObject : NSObject @property (nonatomic, strong) NSNumber *value; // nil表示"不适用" @end // MyDataObject.m #import "MyDataObject.h" @implementation MyDataObject - (NSComparisonResult)myCompare:(MyDataObject *)otherObject { // 处理"不适用"排序规则:所有不适用项排末尾 if (!self.value && otherObject.value) { return NSOrderedDescending; } if (self.value && !otherObject.value) { return NSOrderedAscending; } if (!self.value && !otherObject.value) { return NSOrderedSame; } // 正常比较double数值 return [self.value compare:otherObject.value]; } @end
2. 修正故事板的列排序设置
针对目标列:
- Sort Key设置为
self(表示对数据模型对象本身排序) - Selector保持为
myCompare:
这样设置后,表视图会直接对MyDataObject实例调用自定义比较方法,而非对其内部的NSNumber属性调用。
3. 代码手动设置排序描述符(可选,替代故事板设置)
如果不想依赖故事板配置,可在视图加载时手动添加排序描述符:
- (void)viewWillAppear { [super viewWillAppear]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"self" selector:@selector(myCompare:)]; [self.tableView setSortDescriptors:@[sortDescriptor]]; }
4. 确保数据源返回模型对象
数据源方法要返回MyDataObject实例,显示时再处理数值或"不适用"的展示逻辑:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { MyDataObject *data = self.dataArray[row]; if ([tableColumn.identifier isEqualToString:@"valueColumn"]) { return data.value ? [NSString stringWithFormat:@"%.2f", data.value.doubleValue] : @"不适用"; } return nil; }
关键注意点
- 自定义比较方法必须定义在数据模型类上,参数类型要匹配同类型模型对象
- Sort key设为
self才会对模型对象本身调用自定义方法,设为属性名则会对属性值调用方法 - "不适用"项的排序逻辑要在比较方法中优先判断,确保符合需求的排序位置
内容的提问来源于stack exchange,提问作者johnpurlia
相关产品推荐
相关产品推荐

