MPMediaQuery is always nil for Movie or TV Shows

Hello,


I can no longer query for user's Movie or TV Shows. This used to work before iOS 9.


    MPMediaPropertyPredicate *predicate =
        [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInteger:MPMediaTypeMovie] forProperty:MPMediaItemPropertyMediaType];
    MPMediaQuery *query = [[MPMediaQuery alloc] init];
    [query addFilterPredicate:predicate];
    NSArray *items = [query items];


Returns nothing. As does MPMediaTypeTVShow.


Any hints ? Thanks.

Post not yet marked as solved Up vote post of Jot Down vote post of Jot
558 views

Replies

Bump up on this question. This completely broke in iOS9 with no word from Apple - the docs still show it as working. I filed a radar but received no response. Thanks.

You can query iTunes movies using the ITLibrary with Cocoa.

ITLibrary

AVPlayer seems to have issues with the DRM, even if it says it's DRM free. Maybe Apple can fix this in the future.

You will also need to download the movie from the macOS Apple TV app first, otherwise the item.location will always return nil.


import Cocoa
import iTunesLibrary
import AVFoundation
import AVKit

class ViewController : NSViewController {

    @IBOutlet var videoView: AVPlayerView!
    
    var videoUrl : URL?

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view.
                
        do {
        
            let library = try ITLibrary.init(apiVersion: "1.0")

            if library != nil {
                
                let mediaItems = library.allMediaItems
                
                for item in mediaItems {
                    
                    if item.isVideo {
                        
                        if item.isDRMProtected == false {
                            
                        
                            if item.title == <Video Title> {
                                
                                print(item.title)

                                print("item.location: \(item.location)")
                                print("item.isDRMProtected: \(item.isDRMProtected)")
                                print("item.isUserDisabled: \(item.isUserDisabled)")
                                print("item.isCloud: \(item.isCloud)")
                                print("item.locationType: \(item.locationType)")
                                
                                videoUrl = item.location


                            }

                        }
                        
                    }
                    
                }
                                
            }
            
        } catch {
            
            print("error")
            
        }
        
        DispatchQueue.main.async {
            
            if self.videoUrl!.startAccessingSecurityScopedResource() {
                
                print("access")
                
                do {
                    
                    let data = try Data.init(contentsOf: self.videoUrl!)
                                        
                    let fileManager = FileManager.default
                    var path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
                    path = path + "/video.mov"

                    let url = URL.init(filePath: path)
                    try data.write(to: url)
                    
                    let player = AVPlayer(url: url)

                    let playerLayer = AVPlayerLayer(player: player)
                    
                    playerLayer.backgroundColor = NSColor.black.cgColor
                    playerLayer.frame = self.view.bounds
                    playerLayer.videoGravity = .resizeAspect
                    self.view.layer?.sublayers?
                        .filter { $0 is AVPlayerLayer }
                        .forEach { $0.removeFromSuperlayer() }
                    self.view.layer?.insertSublayer(playerLayer, at: 0)

                    playerLayer.magnificationFilter = .nearest
                    playerLayer.player?.play()
                    
                } catch {
                    
                    //
                    
                }
                
                self.videoUrl?.stopAccessingSecurityScopedResource()
                
            }

        }

        
    }
    
    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

}