Optimize Nspredicate with Magicalrecord

Asked

Viewed 51 times

0

First of all follow my model:

xcdatamodel

Classes:

@interface MMEAlbum : NSManagedObject

... outras propriedades
@property (nonatomic, retain) NSNumber *album_upcoming;
@property (nonatomic, retain) NSSet *songs;

@end

--------
@interface MMESong : NSManagedObject

@property (nonatomic, retain) NSNumber *song_id;
@property (nonatomic, retain) NSString *song_name;
@property (nonatomic, retain) MMEAlbum *album;

@end

Populating the bank:

//Parse album
MMEAlbum *newAlbum              = [MMEAlbum MR_createInContext:self.managedObjectContext];
newAlbum.album_active           = [albumDic active];
newAlbum.album_banner_text      = [albumDic banner_text];
... demais propriedades

// Parse Songs
for (NSDictionary *songDic in allSongs)
{
MMESong *newSong    = [MMESong MR_createInContext:self.managedObjectContext];
newSong.song_id     = [songDic id_song];
newSong.song_name   = [songDic name_song];
newSong.album       = newAlbum;
}

//Save context
[self saveDefaultContext];

Let’s get to the problem, at some point I need to do a search of a song by name via searchBar and show the result in a table:

// Esse método é acionado toda vez que uma letra é digitada no teclado
- (NSArray *)searchTracksWith:(NSString *)string
{
NSPredicate *filterTracks = [NSPredicate predicateWithFormat:@"song_name contains[c] %@", string];
NSArray *result = [MMESong MR_findAllWithPredicate:filterTracks];

return result;
}

I have 80,000 (eighty thousand) songs registered in the bank and when I perform the search using the above predicate besides being slow it freezes my view.

I tried to use this other predicate by searching through the parent root:

NSPredicate *filterTracks = [NSPredicate predicateWithFormat:@"ANY songs.song_name contains[c] %@", string];
NSArray *result = [MMEAlbum MR_findAllWithPredicate:filterTracks];
return result;

Improved response time, but nothing very pleasing.

Any idea how to create a NSPredicate efficient for this type of consultation?

2 answers

1

iTSangar,

Try to place this process inside a thread

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

});

1


Actually the problem is not the NSPredicate, this type of object was not made to optimize the performance of your queries, it is a convenience for you to write queries more say "readable".

The problem is more related to competition, probably the best way for you to solve this, would be by using a NSManagedObjectContext in concurrent mode the thread you are using (which is very likely to be the main one, which is why you see the interface freeze while running the query).

This is a common problem and can be more complicated, especially if you need to synchronize changes between one thread and another.

While researching, I found two references that can help you a lot:

  1. A Guide to Core Data Concurrency
  2. Common Background Practices

I hope it helps you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.