是否可以在核心数据中使用自定义sqlite函数?

时间:2012-03-06 12:59:00

标签: objective-c ios sqlite core-data

似乎没有任何关于这个在线,我需要运行从用户当前位置的距离排序的获取查询。我的第一个计划是创造一个短暂的财产......

- (CLLocationDistance)distance {
    return [self.location distanceFromLocation:locationManager.location];   
}

但后来我发现核心数据不会基于瞬态属性获取,我认为可能是这种情况,因为fetch被转换为带有ORDER BY子句的SELECT语句,所以我的distance属性需要存在于数据库中。

好的,所以我的第二个想法是实现这个,就像我在另一个使用SQLite而没有Core Date的项目中那样使用sqlite3_create_function创建的自定义sqlite函数...

static void sqliteDistance(sqlite3_context *context, int argc, sqlite3_value **argv) {
    if(sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL) {
        sqlite3_result_null(context);
    } else {
        sqlite3_result_double(context, [locationManager.location distanceFromLocation 
            [[CLLocation alloc] initWithLatitude: sqlite3_value_double(argv[0]) longitude: sqlite3_value_double(argv[1])]]);
}

}

现在问题是如何从核心数据获取查询中调用此函数?我猜它可能不可能,因为核心数据的目的是抽象出后备存储的细节,但也许有人知道不同?

3 个答案:

答案 0 :(得分:1)

你说得对,使用Core Data是不可能的。不要忘记其他后备存储类型是可能的。它将如何针对XML执行该查询?

如果您只需要对结果进行排序,为什么在执行获取后没有在数组上设置排序描述符(假设数据集不是太大)?

答案 1 :(得分:0)

我打算建议走另一条路。

从您的自定义函数看,您正在进行某种类型的GIS工作。我只是做了一个快速的谷歌,看到有一个sqlite的GIS扩展:Gaia-SINS

我认为你最好滚动你自己的sqlite库并添加这样的扩展,利用其他人的GIS计算。为什么在其他人为你完成时推出自己的GIS方程?

作为起点,请参阅其他SO问题:compiling-custom-sqlite-for-an-iphone-app

答案 2 :(得分:0)

无法在获取请求中调用瞬态属性。在找到解决方法后的几天,我处理同样的问题。我计算每个元素的距离并选择n个第一兴趣项。 以下方法在NSFetchedResultsController上获取多次搜索的结果,并返回p_NumberArroundMe的数量。

-(void) filteredCustomerPortfolioArroundMe:(NSInteger)p_NumberArroundMe
                                       for:(NSFetchedResultsController*)p_FetchedResultsController
{
    NSFetchRequest *allEtabfetchRequest = [[NSManagedObjectModel CRMManagedObjectModel] fetchRequestFromTemplateWithName:@"AllEtablissements" substitutionVariables:nil];
    NSArray *allEtabInDatabase = [[NSManagedObjectContext sharedManagedObjectContext] executeFetchRequest:allEtabfetchRequest error:nil];

    NSArray *sortedList = [allEtabInDatabase sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"distanceFromUser" ascending:YES]]];

    if ([sortedList count] > p_NumberArroundMe) {
        NSRange aRange;
        aRange.location = 0;
        aRange.length = p_NumberArroundMe;
        sortedList = [sortedList subarrayWithRange:aRange];
    }

    NSMutableArray* keyList = [NSMutableArray array];
    for (SPIREtablissementMin* item in sortedList)
    {
        [keyList addObject:item.partner];
    }

    NSPredicate *predicateArroundMe = [NSPredicate predicateWithFormat:@"partner IN %@",keyList];

    [p_FetchedResultsController.fetchRequest setPredicate:predicateArroundMe];
    [self performFetch:p_FetchedResultsController];
}