CoreData按关系排序

时间:2016-05-28 13:23:16

标签: ios objective-c swift core-data nssortdescriptor

我的关系如下图所示。

CoreData relation

我想首先按活跃促销活动然后按开始日期对活动进行排序。如果当前日期在开始日期和结束日期之间,则促销活动。不幸的是,由于CoreData,我无法使用瞬态属性进行排序。在我的控制器中,我没有使用fetch控制器。

有没有办法实现这个目标?

更新

我遵循排序描述符:

// First is incorrect
[NSSortDescriptor(key: "promotion.start", ascending: false), 
NSSortDescriptor(key: "start", ascending: true)]

谓词(但他们没问题):

let promotionsPredicate =
    NSPredicate(format: "(%@ >= promotion.start && %@ <= promotion.end) && " +
                "(ANY promotion.cities.id == %@)", NSDate(), NSDate(), objectID)
let eventsPredicate =
    NSPredicate(format: "start >= %@ && venue.city.id == %@",
                                NSDate(), objectID)

let subpredicates = [eventsPredicate, promotionsPredicate]                    
let compoundPredicate NSCompoundPredicate(orPredicateWithSubpredicates: subpredicates)

这是请求(我正在使用CoreStore,但想法应该清楚):

class func pagedEventsForPredicateSortedByInPromoAndStartDate(predicate: NSPredicate,
                                                              descriptors: [NSSortDescriptor],
                                                              fetchOffset: Int,
                                                              fetchLimit: Int) -> [Event] {

    return CoreStore.fetchAll(From(Event),
                              Where(predicate),
                              OrderBy(descriptors),
                              Tweak { (fetchRequest) -> Void in
                                fetchRequest.fetchOffset = fetchOffset
                                fetchRequest.fetchLimit = fetchLimit
                                fetchRequest.returnsObjectsAsFaults = false
        }) ?? []
}

2 个答案:

答案 0 :(得分:1)

据我所知,你必须得到所有Event个对象,但只是按照正确的顺序。要做到这么复杂的顺序,包括关系,据我所知你必须获取所有事件,然后使用NSArray's方法对它们进行排序

- (NSArray<ObjectType> *)sortedArrayUsingComparator:(NSComparator)cmptr

以下是代码片段

<强> 1。从核心数据中获取

// get the right context here
NSManagedObjectContext *yourContext;

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Event"];
// extra line, predicate is nil by default, any other required predicate could be written here
request.predicate = nil;

__block NSArray *results = nil;
[yourContext performBlockAndWait:^{

   NSError *error = nil;
   results = [yourContext executeFetchRequest:request error:&error];

       if (error) {
            // handle error here
        }
    }];

使用核心方法手动获取提取,您可以使用Magical Record或任何其他与Core Data一起使用的框架来连接它。

<强> 2。对结果进行排序

__weak typeof(self) weakSelf = self;

NSDate *now = [NSDate date];
NSArray *sortedResults = [results sortedArrayUsingComparator:^NSComparisonResult(Event *_Nonnull obj1, Event *_Nonnull obj2) {

    BOOL isObj1InActivePromotion = [weakSelf date:now isBetweenDate:obj1.promotion.start andDate:obj1.promotion.end];
    BOOL isObj2InActivePromotion = [weakSelf date:now isBetweenDate:obj2.promotion.start andDate:obj2.promotion.end];

    // if they eather are in active promotion or no, just compare them by start date of the Event
    if (isObj1InActivePromotion == isObj2InActivePromotion) {
        return [obj1.start compare:obj2.start];
    } else {
        return isObj1InActivePromotion ? NSOrderedAscending : NSOrderedDescending;
    }
}];

第3。使用NSDate的其他方法

此方法用于排序方法

+ (BOOL)date:(NSDate *)date isBetweenDate:(NSDate *)beginDate andDate:(NSDate *)endDate
{
    if ([date compare:beginDate] == NSOrderedAscending) {
        return NO;
    }

    if ([date compare:endDate] == NSOrderedDescending) {
        return NO;
    }

    return YES;
}

由于显而易见的原因,我无法检查代码,如果有任何拼写错误,请对不起。

答案 1 :(得分:1)

我建议您在促销实体中创建“isActive”横切属性以计算有效记录。

 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Event"];
 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
                                    initWithKey:@“start” ascending:YES];
 [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
 [fetchRequest setIncludesPropertyValues:YES];
 [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

之后,您可以通过排序来过滤获取结果:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@“isActive == %@", @1];
        NSMutableArray *finalResult = [NSMutableArray arrayWithArray:[results filteredArrayUsingPredicate:predicate]];

HTH。