Custom NSSortDescriptor on complex object

眉间皱痕 提交于 2019-12-12 16:24:54

问题


It's my first post so sorry if I may not respect all the conventions even though I'll try my best. I have always found solutions to my problems on SO before but I'm completely stuck on a rather complex Cocoa problem.

I am trying to achieve a complex sort on a list of CoreData objects. I have a catalog composed of Book objects, which can be part of Saga (first book and its sequels). The simplified structures look like this:

@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;

I'm trying to perform a query on my CoreData db, on Book:

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

and I need a sort in three steps:

1) Sort by book's Genre (not included in the code above because it's not needed), which is performed with:

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

2) Sort by Saga title if the book is part of a Saga

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

Where the custom sort descriptor is defined by:

#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) Sort by Volume Numbering IF it is part of a Saga, otherwise, sort by Book Title. Here is my problem, as I don't know what key to send and what to put in my descriptor (I'm not even sure it's possible).

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

So far, I've found that @"self" allows to send the object being queried but it doesn't seem to allow queries of parameters inside the sent object. For reference, there is some code I tried:

- (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]];
}

Any idea what I can and should do ?

Thanks !

EDIT: there was a type in the last line


回答1:


If you're not using an SQL-based store, you could do this by passing self as your key and compare: as the selector, then implement that custom selector. That is, make a method on your book class called compare: and just have it do all of your logic rather than using multiple sort descriptors.



来源:https://stackoverflow.com/questions/11182297/custom-nssortdescriptor-on-complex-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!