1

I've the following relationship:

Playlist may have one-to-many songs, and Song may belong to one-to-many playlists.

My problem consists in getting the order of a song in a specific playlist - for example,

  • in Playlist 1, the order maybe 3,
  • in Playlist 2, the order maybe 1,
  • in Playlist 3, the order maybe 5, etc.

In addition, the order of the songs within a playlist can be changed as they are listed in a tableview.

I now want to keep track of the orders.

I've tried the following approaches:

  1. Creating an new attribute "PlaylistOrders" for the Song entity - working with a NSSet which represents the orders (order and ManagedObjectId of the Playlist),
  2. Creating a new Entity named "PlaylistOrders" and wiring it to "Song". Also this new entity contains an objectId (ManagedObjectId) as Transformable.

Both approaches seem to be very error-prone - in addition I constantly get a warning such as "'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release".

Is there a better and more sophisticated approach storing and retrieving a Song's order within different playlists?

Ulrich Vormbrock
  • 369
  • 2
  • 13
  • a Playlist may contain many songs - thus: in such case, I should store multiple orders in the playlist, representing song 1 ... song n - for me, it doesn't make sense. Or I take a Dictionary - but as I mentioned above, this causes a lot of troubles – Ulrich Vormbrock Jan 30 '21 at 21:11

2 Answers2

0

In the properties of your songs relationship in the Playlist entity in the Data Model, tick the "Ordered" checkbox. Instead of NSSet, they will be available as NSOrderedSet then.

Eugene Dudnyk
  • 5,553
  • 1
  • 23
  • 48
  • Ok I did check "ordered" in the data model - but the question which arises is: according which criteria the songs are ordered? Timestamp, id, order number - or what else? I want to set the order explicitly, namely depending on the row in the table view. I've a tableview to which I do drag&drop - besides (in editing mode), I'll change the order of the songs - so CoreData has to be in snyc – Ulrich Vormbrock Jan 30 '21 at 21:15
  • How do you normally work with `NSArray`? What defines the order of the elements? The same answer applies to the order in the ordered relationship of the data model, i.e. either the order in which you add new songs to the playlist relationship, or the order in the `NSOrderedSet` which you assign to the relationship. – Eugene Dudnyk Jan 30 '21 at 21:16
  • ok I could set a new attribute to Song, namely "ordeInPlaylist". In such case, I would represent only ONE playlist - but what about the fact that a SONG is represented in multiple playlists and with different orders? – Ulrich Vormbrock Jan 30 '21 at 21:21
  • Since you've mentioned that song can be related to many playlists, it's not clear to which playlist this attribute will apply. – Eugene Dudnyk Jan 30 '21 at 21:24
  • That's why I recommend you to use "Ordered" relationship. The information about the order of the song in the relationship will not be stored in the song entity itself, and you'll be able to add the same song at the different position to different playlists. – Eugene Dudnyk Jan 30 '21 at 21:26
  • exactly - what I need is something like this: [playlist1 : 1], [playlist 2 : 3], [playlist 3 : 2] , etc. But this is - as I mentioned - very troublesome as I need to work with Transformable – Ulrich Vormbrock Jan 30 '21 at 21:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228060/discussion-between-eugene-dudnyk-and-ulrich-vormbrock). – Eugene Dudnyk Jan 30 '21 at 21:27
0

Thanks to Eugene, it now works - I mean the approach with NSOrderedSet.

One hint concerning reordering song items in a tableview - the following code snippet shows how to rearrange the items in the NSOrderedSet and storing them to CoreData - we only need a NSMutableOrderedSet:

func moveSongItemInPlaylist(playlist: Playlist, item: SongItem, fromOrder: Int, toOrder: Int) {
    
    let orderedSet = playlist.mutableOrderedSetValue(forKey: "songItems")
    
    let indices = IndexSet(integer: fromOrder)
    
    if (fromOrder > toOrder) {
        // we're moving up
        orderedSet.moveObjects(at: indices, to: toOrder)
    } else {
        // we're moving down
        orderedSet.moveObjects(at: indices, to: toOrder - indices.count)
    }
    
    do {
        try self.managedObjectContext.save()
    } catch {
        print(error)
    }
}
Ulrich Vormbrock
  • 369
  • 2
  • 13