【问题标题】:Is it possible to use a custom sqlite function in core data?是否可以在核心数据中使用自定义 sqlite 函数?
【发布时间】:2012-03-23 23:02:52
【问题描述】:

似乎与此在线无关,我需要运行按与用户当前位置的距离排序的 fetch 查询。我的第一个计划是创建一个临时属性...

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

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

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

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

}

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

【问题讨论】:

  • 您的问题是“您能否将自定义 SQLite 函数与 Core Data NSSQLiteStoreType 一起使用”。那将是一个不。您尝试完成的任务是按与已知位置的距离对 Core Data 结果进行排序,这很有可能,但将是一个不同的问题。
  • @quellish 是对的。为什么不使用没有核心数据的 SQLite,顺便说一句?

标签: objective-c ios sqlite core-data


【解决方案1】:

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

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

【讨论】:

  • 我猜在内存排序后查询就足够了,因为数据集不应该太大,但所有逻辑都通过 NSFetchedResultsController 运行
  • 你不能在获取控制器的获取请求上设置排序描述符吗?
  • 是的,但唯一支持的排序是通过 sqlite 可用的排序,因为排序是在查询时应用的。所以没有瞬态属性或方法调用
【解决方案2】:

我会建议走一条不同的路。

从您的自定义函数看来,您正在做某种 GIS 工作。我刚刚快速谷歌了一下,发现有一个用于 sqlite 的 GIS 扩展:Gaia-SINS

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

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

【讨论】:

  • 谢谢,但这意味着放弃核心数据,这可能涉及重写大约 50% 的应用程序。我想要做的唯一计算是距离,所以我认为这将是相当大的杀伤力
【解决方案3】:

无法在获取请求中调用瞬态属性。在找到解决方法后,我在同一问题上工作了很多天。我计算每个元素的距离并选择 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];
}

【讨论】:

    猜你喜欢
    • 2012-07-05
    • 2010-10-02
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 2015-04-30
    • 2013-03-30
    • 1970-01-01
    • 2011-09-22
    相关资源
    最近更新 更多