Reputation: 80
I have an app that I want to cycle through music. Basically play 15 secs of a song then move on to the next one.
I have a struct (MusicLibrary) that holds an array of song information (a struct called SongItem) including the persistentID of the songs on the iPhone. This struct is working perfectly and if I just print out the names of the songs it works. (Structs at the bottom of this post)
I then have a function (playTheSong) that uses the persistentID i have stored in the songs object with the MPMusicPlayerController - part of the MediaPlayer library.
What happens is the when the button is pressed the first song starts to play. ALL the song persistentIDs are printed to the debugger output and I am not sure why. After 15 seconds the first song stops - I added this timer in an attempt to then move onto the next song, but anything I do here doesn't work. I think it is because the loop through the song structs is executing immediately and that is my problem.
I know I am doing something really silly here, but can't put my finger on it.
Note: This will only work on a phone as the simulator doesn't have a music library.
This is my ViewController.
import UIKit
import MediaPlayer
class RunningMusicViewController: UIViewController {
var myMusic = MusicLibrary()
let myMusicPlayer = MPMusicPlayerController()
var timer: Int = 15
var clock = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func startMusicButton(sender: AnyObject) {
// Get first song of our quiz and play it - Use the persistent ID.
let songs = myMusic.getSongs()
let totalSongs = songs.count
clock = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "countdown", userInfo: nil, repeats: true)
for index in 0..<totalSongs {
playTheSong(songs, index: index)
}
}
func playTheSong(songsInQuiz: [SongItem], index:Int) {
let songToPlay: SongItem = songsInQuiz[index]
print("Song ID=" + String(songToPlay.persistentID))
let predicate = MPMediaPropertyPredicate(value: Int(songToPlay.persistentID), forProperty: MPMediaItemPropertyPersistentID)
let songQuery = MPMediaQuery()
songQuery.addFilterPredicate(predicate)
myMusicPlayer.setQueueWithItemCollection(songQuery.collections![0])
myMusicPlayer.play()
}
func countdown() {
timer--
// When the countdown hits zero we should stop the song.
if timer==0 {
myMusicPlayer.stop()
clock.invalidate()
timer = 15
}
}
}
This is the MusicLibrary struct.
import Foundation
import MediaPlayer
struct MusicLibrary {
var musicLibrary: [SongItem] = []
let query = MPMediaQuery.songsQuery()
var mediaCollection : MPMediaItemCollection {
return MPMediaItemCollection(items: query.items!)
}
mutating func addSongs() {
for index in 0..<mediaCollection.count {
let mediaItem = mediaCollection.items[index]
let songItem = SongItem(
title: mediaItem.title!,
album: mediaItem.albumTitle!,
artist: mediaItem.artist!,
artwork: mediaItem.artwork!,
persistentID: mediaItem.persistentID,
genre: mediaItem.genre!
)
musicLibrary.append(songItem)
}
}
func getSong(index: Int)->SongItem {
return musicLibrary[index]
}
func getSongs()->[SongItem] {
return musicLibrary
}
}
And the SongItem Struct
import Foundation
import MediaPlayer
struct SongItem {
var title: String
var album: String
var artist: String
var artwork: MPMediaItemArtwork
var persistentID: UInt64
var genre: String
init(title: String, album: String, artist: String, artwork: MPMediaItemArtwork, persistentID: UInt64, genre: String) {
self.title = title
self.album = album
self.artist = artist
self.artwork = artwork
self.persistentID = persistentID
self.genre = genre
}
}
Upvotes: 0
Views: 99
Reputation: 11792
I would change the view controller to something along these lines:
import UIKit
import MediaPlayer
class RunningMusicViewController: UIViewController {
var index = 0
var timer: NSTimer
let myMusic = MusicLibrary()
let myMusicPlayer = MPMusicPlayerController()
let numSecondsToPlay = 15.0
let songs = myMusic.getSongs()
@IBAction func startMusicButton(sender: AnyObject) {
playTheSong(index: 0)
timer = NSTimer.scheduledTimerWithTimeInterval(numSecondsToPlay, target: self, selector: "playNextSong", userInfo: nil, repeats: true)
}
func playTheSong(index: Int) {
let songToPlay: SongItem = songs[index]
print("Song ID=" + String(songToPlay.persistentID))
let predicate = MPMediaPropertyPredicate(value: Int(songToPlay.persistentID), forProperty: MPMediaItemPropertyPersistentID)
let songQuery = MPMediaQuery()
songQuery.addFilterPredicate(predicate)
myMusicPlayer.setQueueWithItemCollection(songQuery.collections![0])
myMusicPlayer.play()
}
func playNextSong() {
myMusicPlayer.stop()
if index < songs.count {
playTheSong(index: index)
index += 1
}
else {
timer.invalidate()
}
}
}
Upvotes: 1