Looking for a way to get the last modified date of music playlists.This is how I get the playlists and trying to get the property value:
if let playlists = MPMediaQuery.playlists().collections as? [MPMediaPlaylist] {
for playlist in playlists {
let date = playlist.value(forProperty: "modificationDateTime") as? Any
print(date)
}
}
Property is from the class header: https://github.com/xybp888/iOS-Header/blob/master/13.0/PrivateFrameworks/MusicLibrary.framework/MIPPlaylist.hAny date property returns nil, other properties, such as "cloudGlobalID", works fine.
Any help would be much appreciated.
dateModified property returns the date I was looking for.
dateCreated also returns when the playlist was created or added (for Apple Music playlists) to the library.
Related
I understand how to enumerate images and video in the photo library using PHPhotoLibrary, but videos added through iTunes as "home videos", and visible only through the new TV app under the Home Video section, don't appear in that enumeration.
Is there another way of querying for them?
Well, it looks like the only other thing you can try to use are the Media Player API's.
https://developer.apple.com/documentation/mediaplayer/mpmediaquery
A query that specifies a set of media items from the device's media
library by way of a filter and a grouping type.
That might work, since I assume that your synced movies are part of the media library and not part of the photo library.
First you need to add the NSAppleMusicUsageDescription to your Info.plist. Then we can use MPMediaQuery and filter out the home video items.
let predicate: MPMediaPropertyPredicate = MPMediaPropertyPredicate(value: MPMediaType.homeVideo.rawValue, forProperty: MPMediaItemPropertyMediaType)
let query: MPMediaQuery = MPMediaQuery.init()
query.addFilterPredicate(predicate)
let items = query.items
for item : MPMediaItem in items!
{
// Here is your home video
}
See the MPMediaTypeHomeVideo item: https://developer.apple.com/documentation/mediaplayer/mpmediatype/mpmediatypehomevideo
Now items should contain all your home videos.
EDIT: I tested it, and it works for me on iOS 12, however title seems to be empty. You can access the video file itself using the assetURL property.
Here's an updated method.
import MediaPlayer
func video() {
MPMediaLibrary.requestAuthorization() { status in
if status == .authorized {
let predicate: MPMediaPropertyPredicate = MPMediaPropertyPredicate(value: MPMediaType.homeVideo.rawValue, forProperty: MPMediaItemPropertyMediaType)
let query: MPMediaQuery = MPMediaQuery.init()
query.addFilterPredicate(predicate)
if let items = query.items {
for item in items {
// Here is your home video
print(item.title ?? "title?")
}
}
}
}
}
you'll need to add this key to your info.plist
Privacy - Media Library Usage Description
I am trying to get the realease year of songs in a music player but all I am getting is nil values returned. I've tried writing it every way I can think of and it always returns nil. I've found very little help on this except that it seems this is a known problem... This is the one resource I found that looks like it might help: Get album year for item in iPod library? but I believe this is objective C. My question is this. Does anyone know how to get the release date of MPMediaItems in Swift code? Or know how to translate the linked article to Swift language for me to try. Thanks a bunch!
func getYear() {
let mediaQuery = MPMediaQuery.songs()
for songs in mediaQuery.items! {
print(songs.title)
print(songs.releaseDate)
print(((songs.value(forProperty: MPMediaItemPropertyReleaseDate)!))
print(songs.getReleaseDate())
}
}
extension MPMediaItem {
#available(iOS 10.0, *)
func getReleaseDate() -> Date? {
return self.perform(#selector(getter: MPMediaItem.releaseDate))?.takeUnretainedValue() as! NSDate? as Date?
}
}
I had the same problem and thanks to the resource you linked, I managed to solve it! I translated the Objective-C code to Swift 4 and it just works like a charm even on iOS 11 with Xcode 9, here's the code:
let yearNumber: NSNumber = item.value(forProperty: "year") as! NSNumber
if (yearNumber.isKind(of: NSNumber.self)) {
let year = yearNumber.intValue
if (year != 0) {
// do something with year
}
}
PHAsset has a creationDate property that gives the creation date of the asset in UTC.
If I take a photo taken at 10:52 PM UTC-6, the creationDate property is 03:52 AM.
How am I supposed to know the 'true' time of the photo taken? No timezone information is supplied with the creationDate property, so I can't adjust this back to 10:52 PM - I have no idea what time zone to just when adjusting it...
I know I can get the EXIF creation date (or attempt to at least) using PHImageManager requestImageDataForAsset and using the data returned there to obtain an EXIF creation date which actually is 10:52 PM, but this results in very slow for performance when the photos are in iCloud (I need this creation date value for all assets in the user's library). Additionally I cannot figure out how to get the EXIF creation date for videos.
I also know there are methods of obtaining a timezone from a CLLocation, which I could use to adjust the creationDate - but these methods are either rate limited and/or inaccurate
Is there another, easier way, to get this original creation date value?
To recap:
A photo is taken at 10:52 PM in UTC-6
PHAsset creation date is 03:52 AM in UTC
I want to know how to get 10:52 PM UTC-6 date/time.
You can try using PHContentEditingInput.
It will be probably slow for iCloud images too but it is worth trying as I don't think there are any other ways to do it :(
This approach does not require ImageIO import and needs less code so maybe it would be somewhat better than PHImageManager requestImageDataForAsset
You can use this PHAsset category to try it quickly:
https://github.com/zakkhoyt/PHAsset-Utility
Can get exif details as below :
let options = PHContentEditingInputRequestOptions()
asset.requestContentEditingInput(with: options) { input, _ in
guard let url = input?.fullSizeImageURL else { return }
guard let image = CIImage(contentsOf: url) else { return }
guard let exif = image.properties["{Exif}"] as? [String: Any] else { return }
print(exif["DateTimeOriginal"] ?? "")
print(exif["SubsecTimeDigitized"] ?? "")
}
This prints:
2021:01:04 11:47:07
177
I'm working on code that looks at the user's videos and passes them along to AVPlayer by way of an AVPlayerItem which takes a URL.
To get all the videos on an iOS device, you can do:
let videoNumber = MPMediaType.anyVideo.rawValue
let predicate = MPMediaPropertyPredicate.init(value: videoNumber, forProperty: MPMediaItemPropertyMediaType)
let query = MPMediaQuery.init()
query.addFilterPredicate(predicate)
if let items = query.items
{
mediaCollection = MPMediaItemCollection(items: items)
// -1 would indicate an error condition
print("number of items in collection is \(mediaCollection?.count ?? -1)")
}
When you select the MPMediaItem you want to use from the items array, there should be an assetURL to go with it.
Trouble is, on my device, all of my assetURL properties are NULL. Coincidentally, while hasProtectedAsset for each of these items is false, isCloudItem for each of these items is true.
How can I come up with a valid assetURL that I can pass along to any media player? It feels somewhat bogus that developers can't get proper references & access to media in a user's iPod library.
I wanna get song's listening times in a certain period. Using MPMediaItemPropertyLastPlayedDate I only get the date of the last time a song was played, so if a I play a song multiple times a day, only the last time will count.
Basically, what I wanna do is getting user's listening history in a certain period (the last 2 days for example.)
Also with MPMediaItemPropertyPlayCount I get the total play count overall.
Any ideas?
Thanks.
I'm working with this right now. My (Swift code) is:
func getPlaysSince(since:NSDate, onSuccess: (tracks: [MediaItem])->(), onFail: (error: NSError?)->()) {
var rValue = [MediaItem]()
let timeInterval = since.timeIntervalSince1970
let query = MPMediaQuery.songsQuery()
let songs = query.items
Logger.logMessage(domain: "Data", level: .Minor, "Checking \(songs.count) songs for those since \(since)")
let then = NSDate()
for song in songs {
if let lastPlayedDate = song.lastPlayedDate {
if lastPlayedDate != nil {
if lastPlayedDate.timeIntervalSince1970 > timeInterval {
Logger.logMessage(domain: "Data", level: .Minor, "\(song.title) at \(lastPlayedDate)")
let item:MediaItem = MediaItem(mediaItem: song as! MPMediaItem)
rValue.append(item)
}
}
}
}
let taken = NSDate().timeIntervalSinceDate(then)
Logger.logMessage(domain: "Data", level: .Minor, "scanned in \(taken) seconds")
onSuccess(tracks: rValue)
}
I've include my entire function, though the key lines are the assignments to query, songs and song, and then the check for lastPlayedDate. lastPlayedDate can be nil (never played this song before).
This code is doing a full check of my entire library 5K songs, and takes about 3 seconds. In my case I'm only interested in my play history since "since"
Use this to get the duration of an MPMediaItem.
MPMediaItem *song;
NSNumber *duration= [song valueForProperty:MPMediaItemPropertyPlaybackDuration];