nbransby
nbransby

Reputation: 381

Is it possible to use a custom sqlite function in core data?

Doesn't seem to be anything about this online, I need to run fetch query ordered by distance from the users current location. My first plan was to create a transient property...

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

But then I found out core data won't fetch based on a transient property, which I thought might be the case as the fetch is turned into a SELECT statement with an ORDER BY clause so my distance property needs to exist in the database.

Ok so my second idea was to achieve this the same way I did in another project that used SQLite without Core Date using a custom sqlite function created with sqlite3_create_function...

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

}

Now question is how would I call this function from a core data fetch query? Im guessing its probably not possible as core data's purpose is to abstract away the details of the backing store but maybe someone knows different?

Upvotes: 4

Views: 913

Answers (3)

tdelepine
tdelepine

Reputation: 2016

Its not possible to call a transient property in fetch request. I work on the same issue many days after found a workaround. I calculate the distance of each elements and select the n first interest items. the following method take the result of multiple search on NSFetchedResultsController and return the number of 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];
}

Upvotes: 0

Peter M
Peter M

Reputation: 7513

I'm going to suggest going down a different path.

It seems from your custom function that you are doing GIS work of some sort. I just did a quick google and saw that there is a GIS extension for sqlite: Gaia-SINS

I think you would be better off rolling your own sqlite library and add an extension such as this, leveraging other peoples GIS calculations. Why roll your own GIS equations when other people have done it for you?

As a starting point, see other SO questions like: compiling-custom-sqlite-for-an-iphone-app

Upvotes: 0

sosborn
sosborn

Reputation: 14694

You are right, this isn't possible using Core Data. Don't forget that other backing store types are possible. How would it execute that query against XML?

If you just need to sort the results why not set a sort descriptor on the array after you perform the fetch (assuming the dataset isn't too large)?

Upvotes: 1

Related Questions