Fondation AV est un framework pour travailler avec les médias audio et visuels sur iOS et OSX. Grâce à AV Foundation, vous pouvez lire, capturer et encoder des données multimédia. Il s’agit d’un cadre assez complet et dans le cadre de ce tutoriel, nous nous concentrerons sur la partie audio. Plus précisément, nous utiliserons le AVAudioPlayer
classe pour lire des fichiers MP3.
J'ai fourni un projet de démarrage dans lequel toutes les actions et les prises sont déjà configurées, avec les méthodes appropriées stubées. Les classes utilisées par le projet sont déjà écrites afin que nous puissions plonger dans le code. Vous pouvez télécharger le projet de démarrage depuis GitHub.
Avant de pouvoir utiliser AV Foundation, vous devez lier le projet à la structure. dans le Navigateur de projet, assurez-vous que votre projet est sélectionné. Sous le Général onglet, allez à Cadres et bibliothèques liés et à partir de là vous choisissez AVFoundation.framework.
FileReader
ClasseDans le projet de démarrage, vous trouverez un fichier nommé FileReader.swift. Ouvrez ce fichier pour voir son contenu.
importer la classe UIKit FileReader: NSObject
Il s'agit d'un simple module de la classe que nous utiliserons pour lire les fichiers à partir du disque. Il hérite de NSObject
. Nous allons implémenter une méthode, readFiles
, qui sera une méthode type. Les méthodes de type vous permettent d'appeler une méthode sur la classe elle-même, le type, par opposition à une instance de la classe. Ci-dessous, la mise en œuvre de la readFiles
méthode.
class func readFiles () -> [String] return NSBundle.mainBundle (). pathForResourcesOfType ("mp3", inDirectory: nil) en tant que! [Chaîne]
Le paquet principal contient le code et les ressources pour votre projet, et c’est ici que nous allons trouver les MP3. Nous utilisons la méthode pathForResourcesOfType (_: inDirectory :)
méthode, qui retourne un tableau contenant les noms de chemins pour le type de ressource spécifié. Dans ce cas, nous recherchons le type "mp3"
. Parce que nous ne sommes pas intéressés par un répertoire spécifique, nous passons néant
.
Cette classe sera utilisée par le Lecteur mp3
classe, sur laquelle nous travaillerons ensuite.
Lecteur mp3
ClasseEnsuite, ouvrez MP3Player.swift et voir son contenu.
import UIKit import Classe AVFoundation MP3Player: NSObject, AVAudioPlayerDelegate
Notez que nous adoptons le AVAudioPlayerDelegate
protocole. Ce protocole déclare un certain nombre de méthodes utiles, dont l’une est audioPlayerDidFinishPlaying (_: avec succès :)
. En mettant en œuvre le audioPlayerDidFinishPlaying (_: avec succès :)
méthode, nous serons avertis lorsque la lecture du fichier audio sera terminée.
Ajouter ce qui suit à MP3Player.swift.
class MP3Player: NSObject, AVAudioPlayerDelegate var player: AVAudioPlayer? var currentTrackIndex = 0 pistes de var: [String] = [String] ()
le joueur
la propriété sera une instance de la AVAudioPlayer
classe, que nous utiliserons pour lire, mettre en pause et arrêter les MP3. le currentTrackIndex
variable garde la trace du MP3 en cours de lecture. Finalement, le des pistes
variable sera un tableau des chemins d'accès à la liste des fichiers MP3 inclus dans l'offre de l'application.
init
remplacer init () pistes = FileReader.readFiles () super.init () queueTrack ();
Lors de l’initialisation, nous invoquons le FileReader
de readFiles
méthode pour récupérer les chemins des fichiers MP3 et stocker cette liste dans le des pistes
tableau. Comme il s’agit d’un initialiseur désigné, nous devons appeler le init
méthode de la superclasse. Enfin, nous appelons queueTrack
, que nous écrirons ensuite.
queueTrack
Ajouter l'implémentation suivante pour le queueTrack
méthode à la Lecteur mp3
classe.
func queueTrack () if (player! = nil) player = nil erreur var: NSError? let url = NSURL.fileURLWithPath (pistes [currentTrackIndex] en tant que chaîne) player = AVAudioPlayer (contentsOfURL: url, erreur: & erreur) si let hasError = erreur // SHOW ALERT OR SOMETHING else player? .delegate = self player ?. prepareToPlay ()
Parce que nous allons instancier une nouvelle AVAudioPlayer
Par exemple, chaque fois que cette méthode est appelée, nous effectuons un petit entretien en définissant joueur
à néant
.
Nous déclarons une option NSError
et une constante url
. Nous invoquons fileURLWithPath (_ :)
chercher le chemin du MP3 actuel et stocker la valeur dans url
. Nous passons le des pistes
tableau en tant que paramètre utilisant currentTrackIndex
comme indice. N'oubliez pas que le tableau de pistes contient les chemins d'accès aux fichiers MP3 et non une référence aux fichiers MP3 eux-mêmes..
Instancier le joueur
, nous passons le url
constante et Erreur
variable dans le AVAudioPlayer
est l'initialiseur. En cas d'échec de l'initialisation, le Erreur
la variable est remplie avec une description de l'erreur.
Si nous ne rencontrons pas d'erreur, le délégué du joueur est défini sur soi
et invoquer le prepareToPlay
méthode sur le joueur. le prepareToPlay
La méthode précharge les tampons et acquiert le matériel audio, ce qui minimise les retards lors de l'appel du jouer
méthode.
jouer
le jouer
La méthode vérifie d’abord si le son joue déjà ou non en vérifiant le nom approprié en jouant
propriété. Si le son ne joue pas, il appelle la jouer
méthode du joueur
propriété.
func play () si joueur? .playing == faux joueur? .play ()
Arrêtez
le Arrêtez
La méthode vérifie d’abord si le lecteur audio est déjà en cours de lecture. Si c'est le cas, il invoque le Arrêtez
méthode et définit le heure actuelle
propriété à 0. Lorsque vous invoquez le Arrêtez
méthode, il arrête simplement l'audio. Cela ne réinitialise pas l'audio au début, c'est pourquoi nous devons le faire manuellement.
func stop () si joueur? .playing == vrai joueur? .stop () joueur? .currentTime = 0
pause
Comme le Arrêtez
méthode, nous vérifions d’abord si le lecteur audio est en train de jouer. Si c'est le cas, nous invoquons le pause
méthode.
func pause () si joueur? .playing == vrai joueur? .pause ()
prochaine chanson
le nextSong (_: Bool)
met en file d'attente la chanson suivante et, si le lecteur est en train de jouer, la reproduit. Nous ne voulons pas que la prochaine chanson soit lue si le joueur est en pause. Cependant, cette méthode est également appelée à la fin du morceau. Dans ce cas, nous voulons jouer la chanson suivante, qui correspond au paramètre songFinishedPlaying
est pour.
func nextSong (songFinishedPlaying: Bool) var playerWasPlaying = false si player? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex ++ si currentTrackIndex> = tracks.count currentTrackIndex = 0 queueTrack) | songFinishedPlaying player? .play ()
le playerWasPlaying
La variable est utilisée pour indiquer si le joueur jouait ou non lorsque cette méthode a été invoquée. Si la chanson jouait, nous invoquons le Arrêtez
méthode sur le joueur
Et mettre playerWasPlaying
à vrai
.
Ensuite, nous incrémentons le currentTrackIndex
et vérifier pour voir s'il est supérieur ou égal à pistes.count
. le compter
La propriété d'un tableau nous donne le nombre total d'éléments dans le tableau. Nous devons nous assurer que nous n'essayons pas d'accéder à un élément qui n'existe pas dans le des pistes
tableau. Pour éviter cela, nous avons défini currentTrackIndex
retour au premier élément du tableau si c'est le cas.
Enfin, nous invoquons queueTrack
pour obtenir la prochaine chanson prête et jouer cette chanson si soit playerWasPlaying
ou songFinishedPlaying
est vrai
.
précédentSong
le précédentSong
méthode fonctionne très similaire à prochaine chanson
. La seule différence est que nous décrémentons la currentTrackIndex
et vérifier si elle est égale à 0. Si c'est le cas, on le met à l'index du dernier élément du tableau.
func previousSong () var playerWasPlaying = false si player? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex-- si currentTrackIndex < 0 currentTrackIndex = tracks.count - 1 queueTrack() if playerWasPlaying player?.play()
En utilisant à la fois le prochaine chanson
et précédentSong
méthodes, nous pouvons parcourir tous les fichiers MP3 et recommencer lorsque nous arrivons au début ou à la fin de la liste.
getCurrentTrackName
le getCurrentTrackName
méthode obtient le nom du MP3 sans l'extension.
func getCurrentTrackName () -> String let TrackName = pistes [currentTrackIndex] .lastPathComponent.stringByDeletingPathExtension return trackName
Nous obtenons une référence à tout ce que le MP3 actuel est en utilisant pistes [currentTrackIndex]
. Rappelez-vous cependant que ce sont les chemins d'accès aux fichiers MP3 et non les fichiers eux-mêmes. Les chemins sont assez longs, car c’est le chemin complet des fichiers MP3.
Sur ma machine, par exemple, le premier élément de la des pistes
tableau est égal à "/Users/jamestyner/Library/Developer/CoreSimulator/Devices/80C8CD34-22AE-4F00-862E-FD41E2D8D6BA". Ce chemin serait différent sur un appareil réel bien sûr.
Nous avons une grande chaîne contenant le chemin d'accès au fichier MP3, mais nous souhaitons simplement connaître le nom du fichier MP3 lui-même. le NSString
La classe définit deux propriétés qui peuvent nous aider. Comme son nom l'indique, le lastPathComponent
propriété retourne le dernier composant d'un chemin. Comme vous l'avez peut-être deviné, le stringByDeletingPathExtension
propriété supprime l'extension.
getCurrentTimeAsString
le getCurrentTimeAsString
méthode utilise le heure actuelle
propriété du joueur
exemple et le renvoie sous forme de chaîne lisible par l’homme (par exemple,., 1:02).
func getCurrentTimeAsString () -> Chaîne var secondes = 0 var minutes = 0 si le temps = player? .currentTime secondes = Int (heure)% 60 minutes = (Int (heure) / 60)% 60 retourne Chaîne (format : "% 0.2d:% 0.2d", minutes, secondes)
le heure actuelle
propriété est de type NSTimeInterval
, qui est juste un typealias
pour un Double
. Nous utilisons des mathématiques pour obtenir le secondes
et minutes
, en nous assurant de convertir temps
à un Int
puisque nous devons travailler avec des nombres entiers. Si vous ne connaissez pas l'opérateur représentant le reste (%), il trouve le reste après la division d'un nombre par un autre. Si la temps
variable était égale à 65, puis secondes
serait égal à 5 parce que nous utilisons 60.
getProgress
le getProgress
méthode est utilisée par le UIProgressView
exemple pour donner une indication de la quantité de MP3 jouée. Ce progrès est représenté par une valeur de 0.0 à 1,0 comme un Flotte
.
func getProgress () -> Float var theCurrentTime = 0.0 var theCurrentDuration = 0.0 si currentTime = player? .currentTime, duration = player? .duration theCurrentTime = currentTime theCurrentDuration = duration renvoie Float (theCurrentTime / theCurrentDuration).
Pour obtenir cette valeur, nous divisons le joueur
de heure actuelle
propriété par le joueur
de durée
propriété, nous stockons ces valeurs dans les variables l'heure actuelle
et la durée actuelle
. Comme heure actuelle
, la durée
propriété est de type NSTimeInterval
et il représente la durée de la chanson en secondes.
setVolume
le setVolume (_: Float)
méthode invoque le setVolume
méthode du joueur
exemple.
func setVolume (volume: Float) player? .volume = volume
audioPlayerDidFinishPlaying (_: avec succès :)
le audioPlayerDidFinishPlaying (_: avec succès :)
méthode est une méthode de la AVAudioPlayerDelegate
protocole. Cette méthode prend comme paramètres la AVAudioPlayer
exemple et un booléen. Le booléen est réglé sur vrai
si le lecteur audio a fini de jouer la chanson en cours.
func audioPlayerDidFinishPlaying (lecteur: AVAudioPlayer, indicateur réussi: Bool) si indicateur == true nextSong (true)
Si la chanson a fini de jouer, nous appelons le prochaine chanson
méthode, passage vrai
depuis que la chanson a fini de jouer tout seul.
Ceci termine la Lecteur mp3
classe. Nous y reviendrons un peu plus tard, après la mise en œuvre des actions du ViewController
classe.
ViewController
ClasseOuvrir ViewController.swift et voir son contenu.
Import de UIKit mport Classe AVFoundation ViewController: UIViewController var mp3Player: MP3Player? var timer: NSTimer? @IBOutlet faible var trackName: UILabel! @IBOutlet faible var trackTime: UILabel! @IBOutlet faible var progressBar: UIProgressView! remplacez func viewDidLoad () super.viewDidLoad () @IBAction func playSong (expéditeur: AnyObject) @IBAction func stopSong (expéditeur: AnyObject) @IBAction func pauseSong (expéditeur: AnyObject) @IBAction func playNext ( expéditeur: AnyObject) @IBAction func setVolume (expéditeur: UISlider) @IBAction func playPreviousSong (expéditeur: AnyObject) écrasé func didReceiveMemoryWarning () super.didReceiveMemoryWarning ()
le lecteur mp3
variable est une instance du Lecteur mp3
classe que nous avons mis en place plus tôt. le minuteur
variable sera utilisée pour mettre à jour le trackTime
et barre de progression
vues chaque seconde.
Dans les prochaines étapes, nous mettrons en œuvre les actions du ViewController
classe. Mais d’abord, nous devrions instancier le Lecteur mp3
exemple. Mettre à jour la mise en œuvre de la viewDidLoad
méthode comme indiqué ci-dessous.
remplacer la fonction viewDidLoad () super.viewDidLoad () mp3Player = MP3Player ()
playSong (_: AnyObject)
Entrez ce qui suit dans le playSong (_: AnyObject)
méthode.
@IBAction func playSong (expéditeur: AnyObject) mp3Player? .Play ()
Dans cette méthode, nous appelons le jouer
méthode sur le lecteur mp3
objet. Nous sommes à un point où nous pouvons commencer à tester l'application maintenant. Exécutez l'application et appuyez sur le bouton de lecture. La chanson devrait commencer à jouer.
stopSong (_: AnyObject)
le stopSong (_: AnyObject)
méthode appelle la méthode stop sur le lecteur mp3
objet.
@IBAction func stopSong (expéditeur: AnyObject) mp3Player? .Stop ()
Exécutez l'application à nouveau et appuyez sur le bouton de lecture. Vous devriez maintenant pouvoir arrêter la chanson en appuyant sur le bouton d'arrêt.
pauseSong (_: AnyObject)
Comme vous l'avez peut-être deviné, le pauseSong (_: AnyObject)
méthode invoque le pause
méthode sur le lecteur mp3
objet.
@IBAction func pauseSong (expéditeur: AnyObject) mp3Player? .Pause ()
playNextSong (_: AnyObject)
IBAction func playNextSong (expéditeur: AnyObject) mp3Player? .NextSong (false)
Dans playNextSong (_: AnyObject)
, nous invoquons le prochaine chanson
méthode sur le lecteur mp3
objet. Notez que nous passons faux
en tant que paramètre, car la chanson n'a pas fini de jouer d'elle-même. Nous commençons manuellement la chanson suivante en appuyant sur le bouton suivant.
previousSong (_: AnyObject)
@IBAction func playPreviousSong (expéditeur: AnyObject) mp3Player? .PreviousSong ()
Comme vous pouvez le constater, la mise en œuvre de la previousSong (_: AnyObject)
méthode est très similaire à celle de nextSong (_: AnyObject)
. Tous les boutons du lecteur MP3 devraient être opérationnels maintenant. Si vous n'avez pas encore testé l'application, ce serait le bon moment pour vous assurer que tout fonctionne comme prévu.
setVolume (_: UISlider)
le setVolume (_: UISlider)
méthode invoque le setVolume
méthode sur le lecteur mp3
objet. La propriété volume est de type Flotte
. La valeur va de 0.0 à 1,0. le UISlider
l'objet est mis en place avec 0.0 comme valeur minimale et 1,0 comme valeur maximale.
@IBAction func setVolume (expéditeur: UISlider) mp3Player? .SetVolume (sender.value)
Exécutez l'application une fois de plus et jouez avec le curseur de volume pour vérifier que tout fonctionne correctement.
startTimer
le startTimer
méthode instancie un nouveau NSTimer
exemple.
func startTimer () timer = NSTimer.scheduledTimerWithTimeInterval (1.0, cible: self, sélecteur: Selector ("updateViewsWithTimer:"), userInfo: nil, répète: true)
le scheduleTimerWithTimeInterval (_: cible: sélecteur: utilisateurInfo: répète :)
initializer prend en paramètre le nombre de secondes entre le déclenchement de la minuterie, l’objet auquel appeler une méthode spécifiée par sélecteur
, la méthode appelée lors du déclenchement de la minuterie, option informations utilisateur
dictionnaire, et si le chronomètre se répète jusqu'à ce qu'il soit invalidé.
Nous utilisons une méthode nommée updateViewsWithTimer (_: NSTimer)
en tant que sélecteur, nous allons donc créer cette prochaine.
updateViewsWithTimer (_: NSTimer)
le updateViewsWithTimer (_: NSTimer)
la méthode appelle le updateViews
méthode, que nous allons mettre en œuvre dans la prochaine étape.
func updateViewsWithTimer (theTimer: NSTimer) updateViews ()
updateViews
le updateViews
la méthode met à jour le trackTime
et barre de progression
vues.
func updateViews () trackTime.text = mp3Player? .getCurrentTimeAsString () si laisse progress = mp3Player? .getProgress () progressBar.progress = progress
le texte
propriété de trackTime
est mis à jour avec le heure actuelle
propriété, formatée comme une chaîne en invoquant le getCurrentTimeAsString
méthode. Nous déclarons une constante le progrès
en utilisant le lecteur mp3
de getProgress
méthode et set progressBar.progress
en utilisant cette constante.
Maintenant, nous devons appeler le startTimer
méthode aux endroits appropriés. Nous devons démarrer le chronomètre dans le playSong (_: AnyObject)
méthode, la playNextSong (_: AnyObject)
méthode et playPreviousSong (_: AnyObject)
méthode.
@IBAction func playSong (expéditeur: AnyObject) mp3Player? .Play () startTimer ()
@IBAction func playNextSong (expéditeur: AnyObject) mp3Player? .NextSong (false) startTimer ()
@IBAction func playPreviousSong (expéditeur: AnyObject) mp3Player? .PreviousSong () startTimer ()
Nous devons également arrêter la minuteur
lorsque les boutons pause et arrêt sont enfoncés. Vous pouvez arrêter le minuteur
objet en invoquant le invalider
méthode sur le NSTimer
exemple.
@IBAction func stopSong (expéditeur: AnyObject) mp3Player? .Stop () updateViews () timer? .Invalidate ()
@IBAction func pauseSong (expéditeur: AnyObject) mp3Player? .Pause () timer? .Invalidate ()
setTrackName
le setTrackName
méthode définit le texte
propriété de trackName
en invoquant getCurrentTrackName
sur le lecteur mp3
objet.
func setTrackName () trackName.text = mp3Player? .getCurrentTrackName ()
setupNotificationCenter
Quand une chanson est terminée, le nom de la chanson suivante doit s'afficher automatiquement et la lecture commence. De plus, lorsque l’utilisateur appuie sur les boutons de lecture, suivant ou précédent, le setTrackName
méthode devrait être invoquée. Le lieu idéal pour cela est le queueTrack
méthode du Lecteur mp3
classe.
Nous avons besoin d'un moyen d'avoir le Lecteur mp3
classe dire le ViewController
classe à invoquer le setTrackName
méthode. Pour ce faire, nous allons utiliser le NSNotificationCenter
classe. Le centre de notification fournit un moyen de diffuser des informations tout au long d'un programme. En s'inscrivant en tant qu'observateur auprès du centre de notification, un objet peut recevoir ces émissions et effectuer une opération. Une autre façon d'accomplir cette tâche serait d'utiliser le modèle de délégation.
Ajoutez la méthode suivante à la ViewController
classe.
func setupNotificationCenter () NSNotificationCenter.defaultCenter (). addObserver (auto-sélecteur: "setTrackName", nom: "SetTrackNameText", objet: nil)
Nous obtenons d’abord une référence au centre de notification par défaut. Nous invoquons ensuite le addObserver (_: sélecteur: nom: objet :)
méthode sur le centre de notification. Cette méthode accepte quatre paramètres:
soi
dans ce casEn passant dans néant
comme dernier argument, nous écoutons toutes les notifications portant le nom SetTrackNameText.
Maintenant, nous devons appeler cette méthode dans le contrôleur de vue viewDidLoad
méthode.
remplacer func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter ()
Pour poster la notification, nous invoquons le postNotificationName (_: objet :)
méthode sur le centre de notification par défaut. Comme je l'ai mentionné plus tôt, nous le ferons dans le queueTrack
méthode du Lecteur mp3
classe. Ouvrir MP3Player.swift et mettre à jour le queueTrack
méthode comme indiqué ci-dessous.
func queueTrack () if (player! = nil) player = nil erreur var: NSError? let url = NSURL.fileURLWithPath (pistes [currentTrackIndex] en tant que chaîne) player = AVAudioPlayer (contentsOfURL: url, erreur: & erreur) si let hasError = erreur // SHOW ALERT OR SOMETHING else player? .delegate = self player ?. prepareToPlay () NSNotificationCenter.defaultCenter (). postNotificationName ("SetTrackNameText", objet: nil)
Si vous testez l'application maintenant et laissez une chanson jouer en boucle, la lecture de la chanson suivante devrait commencer automatiquement. Mais vous vous demandez peut-être pourquoi le nom de la chanson n’apparaît pas lors de la première chanson. le init
méthode du Lecteur mp3
la classe appelle le queueTrack
méthode, mais comme elle n’a pas fini de s’initialiser, elle n’a aucun effet.
Tout ce que nous avons à faire est d’appeler manuellement le setTrackName
méthode après avoir initialisé le lecteur mp3
objet. Ajoutez le code suivant au viewDidLoad
méthode en ViewController.swift.
remplacer func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter () setTrackName () updateViews ()
Vous remarquerez que j'ai aussi appelé le updateViews
méthode. De cette façon, le joueur affiche un temps de 0:00 au début. Si vous testez l'application maintenant, vous devriez avoir un lecteur MP3 entièrement fonctionnel..
Ce didacticiel était plutôt long, mais vous avez maintenant un lecteur MP3 fonctionnel sur lequel vous pouvez construire et développer. Une suggestion est de permettre à l’utilisateur de choisir une chanson à jouer en mettant en œuvre un UITableView
en dessous du joueur. Merci d'avoir lu et j'espère que vous avez appris quelque chose d'utile.