2012-06-25 200 views
3

这是我的第一篇文章,如果我不尊重所有的惯例,尽管我会尽力而为,但是很抱歉。我之前一直在找到解决我的问题的解决方案,但我完全停留在一个相当复杂的可可问题上。复杂对象上的自定义NSSortDescriptor

我想在CoreData对象的列表上实现一个复杂的排序。我有一个由Book对象组成的目录,它可以是佐贺(第一本书及其续集)的一部分。简化的结构是这样的:

@interface Book : NSManagedObject 
@property (nonatomic, retain) NSString * title; 
@property (nonatomic, retain) NSNumber * tomaison; //volume numbering 
@property (nonatomic, retain) Saga *fromSaga; 

@interface Saga : NSManagedObject 
@property (nonatomic, retain) NSString * title; 

我想在我的CoreData数据库执行查询,在书:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:context]; 

,我需要三个步骤排序:

1)排序的书的流派(未包括在上述,因为它不需要代码),这是与执行:

NSSortDescriptor* mainSort = [[NSSortDescriptor alloc] initWithKey:@"ofGenre.title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; 

2)排序佐贺标题如果这本书是一个传奇

NSSortDescriptor* secondarySort = [[SagaTitleSortDescriptor alloc] initWithKey:@"fromSaga" ascending:YES]; 

的一部分,如果自定义排序描述符的定义为:

#define NULL_OBJECT(a) ((a) == nil || [(a) isEqual:[NSNull null]]) 
@interface SagaTitleSortDescriptor : NSSortDescriptor {} 
@end 
@implementation SagaTitleSortDescriptor 
- (id)copyWithZone:(NSZone*)zone 
{ 
    return [[[self class] alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]]; 
} 
- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 
{ 
    if (NULL_OBJECT([object1 valueForKeyPath:[self key]])) { 
     if (NULL_OBJECT([object2 valueForKeyPath:[self key]])) 
      return NSOrderedSame; 
     return NSOrderedDescending;   
    } 
    if (NULL_OBJECT([object2 valueForKeyPath:[self key]])) { 
     return NSOrderedAscending; 
    } 
    return [super compareObject:[(Saga*)object1 title] toObject:[(Saga*)object2 title]]; 
} 
@end 

3)排序方式卷编号,如果它是的一部分佐贺,否则,按书名排序。这是我的问题,因为我不知道发送什么密钥以及要在我的描述符中放什么(我甚至不确定这是可能的)。

NSSortDescriptor* thirdSort = [[SagaTomaisonOrBookTitleSortDescriptor alloc] initWithKey:@"self" ascending:YES]; 

到目前为止,我已经找到了@“自我”允许发送被查询的对象,但它似乎没有允许的发送对象的内部参数的查询。作为参考,我尝试了一些代码:

- (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 
{ 
    if (NULL_OBJECT([(Book*)object1 fromSaga]) && NULL_OBJECT([(Book*)object2 fromSaga])) { 
     return [super compareObject:[(Book*)object1 title] toObject:[(Book*)object2 title]]; 
    } 
    if (NULL_OBJECT([(Book*)object1 fromSaga])) { 
     return NSOrderedDescending; 
    } 
    if (NULL_OBJECT([(Book*)object2 fromSaga])) { 
     return NSOrderedAscending; 
    } 
    return [super compareObject:[(Book*)object1 tomaison] toObject:[(Book*)object1 tomaison]]; 
} 

任何想法我可以做什么,应该做什么?

谢谢!

编辑:有一个在最后一行类型

+0

这是NSFetchRequest的一部分吗?您使用的是什么Core Data支持存储?如果它是SQL后端,则不能将基于代码的排序描述符用于NSFetchRequest。 –

+0

它确实是NSFetchRequest的一部分,我使用的是标准的CoreData模型(.xcdatamodel,NSManagedObjectContext等)。请注意,第二个排序描述符完美工作。 – ameunier

回答

1

如果你不使用基于SQL的商店,你可以通过将自身作为你的钥匙,并比较这样做:作为选择,然后实现定制选择器。也就是说,在您的书籍类中创建一个名为compare的方法,并让它完成所有的逻辑,而不是使用多个排序描述符。

+0

这很有趣。但是,它似乎也不起作用。我在Book类中实现了一个自定义选择器(在类别中更具体),并且它崩溃了。我已经验证了一些非常简单的测试: ' - (NSComparisonResult)specialCompare:(id)other {return NSOrderedSame; }' 而在ViewController中: 'NSSortDescriptor * thirdSort = [[NSSortDescriptor页头​​] initWithKey:@ “自我” 升:是选择:@选择(specialCompare :)]' 难道我做错了什么? – ameunier

+0

附加说明:我不能简单地重写Book.h中的compare:方法,因为这不是我比较两本书的唯一地方,而其他地方有其他排序方法 – ameunier

+0

对我来说这看起来没问题。事故发生在哪里?你收到什么信息? –