How unique is MPMediaItemPropertyPersistentID? - objective-c

How unique is MPMediaItemPropertyPersistentID? Will it even work when synching the list of IDs to another device connected to the same iTunes Account?
I want to implement a iCloud synchronized playlist solution which stores the IDs as a list and I need to know if this will be possible.

As per the documentation (emphasis mine)...
The value of the MPMediaItemPropertyPersistentID identifier persists
across application launches and across syncs that do not change the
sync status of the media item. The value is not guaranteed to
persist across a sync/unsync/sync cycle.
As such, given that it won't even persist on this basis I'd be surprised if it persisted across devices in a sufficiently robust manner, if at all.

In my understanding this is not possible. I think this ID is persistent only for each device. It is no unique identifier for a specific song in the iTunes Store. It is only a ID for your own synced songs.
As you read the documentation, you'll see how fragile this ID could be.
"The value is not guaranteed to persist across a sync/unsync/sync cycle."
So if you sync your song database with iTunes and maybe delete a song from your iOS device and the sync again and put it back to your device, you may not get the same ID again for this song. And for sure not across other devices.
So I think, what you're trying to do will not work, until you get a worldwide identical Identifier for each song of the iTunes catalogue or your own iTunes catalogue on the Mac (where the Mac has to handle the IDs).

The other answers are a little big vague, so here is an answer from my own experiences and tests:
1) You can't use MPMediaItemPropertyPersistentID to get an ID that is equal between devices.
2) The MPMediaItemPropertyPersistentID will change when the device is synced with another iTunes library or all music is removed from the device and then synced again.
The ID get's created and stored by iTunes when the song is synced on the device. If it's unsynced, the ID get's deleted.

In case somebody else lands here, like me, using a Google search:
I confirmed what middaparka said above after an iOS upgrade of my device, when my music app tried to use persistentIDs from before the upgrade. The IDs had changed, and I ended up (unwittingly) listening to many songs from my library that I don't normally listen to...
So I took middaparka's advice and constructed a persistentKey by exclusive-oring the hashes from title, artistName, albumTitle and duration. Building the persistentKey during Core Database initialization will be save time later, by avoiding multiple string comparisons when fetching items in "normal operating code."
The persistentKey strategy worked properly for songs. However, when I made a hash for albums from title, artist and releaseYear, I ended up with one collision.
I had two self-titled albums by different artists released in 1976. When the hashes for the album title and the artist were exclusive-ored, they cancelled each other out. I ended up using the hash for the duration instead of the artist, and that worked.
I may end up refining the algorithm for generating the persistentKeys later...

Related

Data Modeling Issue

just started using Keen.IO…very nice product. I have a question please on data modeling:
I am tracking mobile app registration events that have the following attributes:
Device Id,
Platform,
Manufacturer,
Marketing Version,
Language and
Latitude and Longitude
The problem is that the mobile app sends this registration every time the device changes location. In a way, it is to maintain the device latest location and keep track of historic changes. I created a new collection for devices and it seems to be OK as I am able to select_unique the keen.location.coordinates to draw the devices on a map.
The question though is how would I know the latest location update? So now I have several events in the collection for the same device (uniquely identified by a device id) but no way of finding the latest!
Thank you for any pointer.
Regards,
Khaled
It is technically possible to use existing Keen query types to retrieve the latest position of a device as you require, the problem is doing so is inefficient and doesn't scale well (mainly because Keen is designed to store/query event data, not entity data). You'd have to plug the Device Id you retrieve from the select_unique into individual queries for each device to find the latest location. Doing so would bump you up against concurrency and/or rate limiting fairly quickly.
That being said, that leaves you with a few options:
Use Keen's S3 integration. This feature writes all of your raw events to S3 for consumption however you see fit. You could use this data to create a pipeline to a separate entity database which would allow you to retrieve the device's latest location. Note: there is an extra charge for this feature.
Post device/location data to a separate entity database at the same time you're sending the event to Keen, and use that database as the source of the device's latest location.
Either of these options will work, it just depends on how you'd like to implement/manage data collection in your application.
I think you can achieve this by combining a select_unique query with a group_by clause and looking at the last item in the result.
Though, as terrhorn noted – it's not a scalable solution. I wouldn't use it for anything other than dashboarding.
Here's a quick example:
var query = new Keen.Query("select_unique", {
eventCollection: "devices",
targetProperty: "location",
group_by: "device_id"
});
The result will look something like this:
{
"result": [
{
"device_id": "4252f729-7bdc-a487-be15-984999a96683",
"result": [
"location_1",
"location_2"
]
}
]
}
NOTE: This is theoretical – I'm not sure if Keen sorts the result of the group_by by the order in which the events came in or not – but it's a good assumption to test. I don't see why they wouldn't.

Does Deezer APIs track method return unreliable results?

Here are some example (setting italy as country):
http://api.deezer.com/2.0/track/2566127 says the track is not readable, but I can play it both from deezer.com and from an API app, the same for http://api.deezer.com/2.0/track/7960580
http://api.deezer.com/2.0/track/3259613 says the track is not readable, it is actually not existent (and usually for not existent track the API return error)
Some other times a track (which used to exist) results as not existent (e.g. http://api.deezer.com/2.0/track/17737916 Beatles - Till There Was You) both from API and deezer.com player (http://www.deezer.com/it/track/17737916) BUT if I search the song using the tile from deezer.com I can see that the track is available with a new id (APIs don't give me the "alternative" id, though).
Am I doing something wrong or the APIs responses are sometime just nor reliable?
Tracks in the Deezer API have now an "alternative" field as well as "available_countries" to deal with those country availability issues. You can check it in the API Explorer.
This is however not working for deprecated track ids, because queries on unexisting tracks will just result in a DataException. You could use ISRC codes to work around that, that we now provide as well. Hope this helps.

Detecting iTunes playlist folders on a device

Through iTunes, you can create playlist folders that are nested arbitrarily deep. When you copy those playlist folders to your iOS device, iTunes is able to detect that they're folders, and allows you to drill down to the point where you ultimately get songs. Any idea how they do that?? I've been trying to figure this out for days.
When I query for a specific persistentID of a known folder, the only things I can see about it that are different from a playlist that contains songs are:
playlist.mediaTypes = 4359 (this is
Music|Podcast|Audiobook|Movie|VideoiTunes) whereas a normal playlist
will not mix audio types and video types
value for property
MPMediaPlaylistPropertyPlaylistAttributes contains 2
(MPMediaPlaylistAttributeSmart), whereas a normal playlist contains 0
the item count will be equal to the total number of items on the
device
But, that's it! I don't see any way to get at the sub-folders. Or, when interrogating a playlist or subfolder that's contained within a folder, I don't see any way to tie it to the parent.
Apple does it in iTunes, so there must be a way. Are they using some private API?
There are the following undocumented properties that can get you what you are looking for using MPMediaPlaylist's valueForProperty method: #"isFolder", and #"parentPersistentID".
Note, these are not documented and do not appear in any header files, so use of them might be considered use of a 'private API' according to Apple's application submission rules.
I've opened a bug report to Apple asking that those be made available in header files, and also asking to clarify whether they are considered to be part of a private API.

Is there a way to get Address Book contact ID's from Sync Services contact ID's?

When getting the modified contacts from Sync Services, through the applyChange:forEntityName:remappedRecordIdentifier:formattedRecord:error method. The IDs in the address book are of the form 2C13E20E-6B24-4090-81FA-7A1E8B28119B, and even though some IDs of this kind are present in the ISyncChange * object, those are not actual contact ID's that can be found in the address book...
Is there a way to find out from Sync Services what a certain contact's ID is in the Address Book?
The reason for asking is that when saving large pictures for contacts in the Address Book, Sync Services does not save those pictures in their internal data storage. Therefore, contacts that have been modified or added with a large picture will be returned by Sync Services without the picture, basically offering incomplete information.
I need to get the Address Book ID, so that I can look up the contact's picture in ~/Library/Application Support/Address Book/Images/
Thanks!
It's a bad idea to rely on the Address Book id relating to an image in ~/Library/Application Support/Address Book/Images/ - you'd be better off finding an API that provides you the data you want to work with, because you aren't guaranteed that the image will be there then, or later (after an upgrade, this could all change!).
After a small amount of research, it appears that the api you want is documented here : http://developer.apple.com/library/mac/#documentation/UserExperience/Conceptual/AddressBook/Tasks/AccessingData.html#//apple_ref/doc/uid/20001023-103617
It's a little unwieldy because you necessarily need to understand their ABImageClient protocol and provide a callback, but I don't think it's that bad. This approach is much better than what you were doing - it's the Apple sanctioned way of getting this data and you won't have to worry about it breaking in the future.

Address Book contacts in Core Data

What’s considered ‘best practice’ when saving Address Book contacts in Core Data?
I’m writing an iPhone App, based on Core Data, where I need to save and recall Address Book contacts as part of the data model.
In the UI I plan to present a screen where the user can pick a contact from the current Address Book, create a new contact to store in the Address Book, or just create a ‘one-off’ contact with no saved record, local to the App only. These contacts are tracked in the context of the orders they have made, and not all contacts will require saving outside the App itself.
It feels ‘wrong’ to copy the data from the Address Book if using an existing entry, but not sure what to do if an Address Book record is edited or deleted.
I only need to track name and photo for the purposes of the App, so gut-reaction is to store the ABRecordID, and—because these can apparently change(!)—the first and last name, and only update local record if it’s updated (how to track that?).
Or can you store a ABRecordRef directly? (I imagine they aren’t persistent?)
I’ve done some searching on Google, and here, but can’t find any code samples or discussion on the integration of Core Data and Address Book in this manner; just lots of stuff on each in isolation.
Any one with some experience/gotchas on this subject point them out, or point me in the direction of some more reading?
Thanks.
Andy W
I would store the ABRecordID and then handle the situation for when they change although I have not personally seen a case where they change except when the user deletes all data and restores it from another source (moving from MobileMe to Google for example).
See Apples online Documentation on how to handle changing ids and what to store.