0

I am adding functionality to delete a song (playlistTrack) from a Playlist. Each playlistTrack has a playlist_track_number associated with it, so we know what order the songs are to be played in. Thus, after deleting a playlistTrack I need to assign all the playlistTracks that follow a new playlist_track_number, namely 1 less than their previous playlist_track_number.

My code here runs fine once and then crashes with the console displaying "'Can't do regex matching on object 3." any help?

NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];


NSPredicate *predicateList = [NSPredicate predicateWithFormat:@"(playlist.name CONTAINS[cd] %@)", activePlaylistString];

NSArray *newArray = [[NSArray alloc]init];
newArray = (NSArray*)[Playlist_Track MR_findAllWithPredicate:predicateList];

for (int i = (delTrack + 1); i <= [newArray count]; i++) {

    localContext = [NSManagedObjectContext MR_contextForCurrentThread];

    NSString *nextTrackNumberString = [NSString stringWithFormat:@"%i",i];

    NSPredicate *nextPredicate = [NSPredicate predicateWithFormat:@"(playlist.name CONTAINS[cd] %@) AND (playlist_track_number MATCHES [cd] %@)", activePlaylistString, nextTrackNumberString];

    nextTrack = [Playlist_Track MR_findFirstWithPredicate:nextPredicate inContext:localContext];

    if (nextTrack) {

        int j = i-1;

        nextTrack.playlist_track_numberValue = j;

        [localContext MR_saveToPersistentStoreWithCompletion:nil];
    }

    if (!nextTrack) {
        //Do Nothing
    }

}
Fluffhead
  • 845
  • 1
  • 9
  • 21

3 Answers3

0

Instead of doing lots of different fetches, just do one fetch to get all of the objects that need to be updated, then iterate over them and perform the updates. Depending on the number if items you can batch the response from the fetch or return the items as faults and then batch the saves.

Wain
  • 118,658
  • 15
  • 128
  • 151
0

This error tell about you trying to use 'NSPredicate' with inappropriate types (playlist_track_number MATCHES [cd] %@) I suppose you are trying to MATCH number playlist_track_number with string.

BTW i suppose have a not very efficient architecture in your CoreData. This delete operation will took a very long time (find and fetch all than multiple find one in a loop) Also your current architecture does not allow to use one playlistTrack in 2 or more playlists So it is good idea to remove playlist_track_number property from playlistTrack

To create fast inserts and removes from playlist you can use linked list or doubly-linked list structure. When each playlistTrack item will have relationship to next (and previous) item. In playlist entity you can have only relationship to head (and tail) items also good to have count property.

Also you can use NSOrderedSet for one-to-many relationship in CoreData this will allow you to insert item at index and remove item at index (But it have a lot of unresolved bugs for current moment)

Both variants will allow you to have track number/order without playlist_track_number property

Flop
  • 153
  • 4
  • Thanks you for the suggestion, but it seems there are lots of unreselvedbugs with NSOrderedSet and removing items. They have been around for a long time and there are workarounds, but it seems Apple hasn't fixed yet: http://stackoverflow.com/questions/7385439/exception-thrown-in-nsorderedset-generated-accessors/7922993#7922993 – Fluffhead Aug 06 '13 at 04:23
  • That's true. We are still awaiting fixes from apple. – Flop Aug 06 '13 at 07:57
0

Using Flop's suggestion, I reworked the code as follows. This is hardcoded to always delete the track at index 3, but that can be changed easily by passing a parameter into the method.

NSArray *trackList = [[NSArray alloc]init];

NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];

Playlist *selectedPlaylist;

selectedPlaylist = [Playlist MR_findFirstByAttribute:@"name" withValue:activePlaylistString];

trackList = (NSArray*)selectedPlaylist.playlist_trackSet;

NSMutableArray *newArray = [trackList mutableCopy];

NSUInteger delIndex = 3;

[newArray removeObjectAtIndex:delIndex];

trackList = newArray;

NSOrderedSet *trackSet = (NSOrderedSet*)trackList;

selectedPlaylist.playlist_track = trackSet;

[localContext MR_saveToPersistentStoreWithCompletion:nil];
Fluffhead
  • 845
  • 1
  • 9
  • 21