Fondazione AV è un framework per lavorare con supporti audio e video su iOS e OSX. Utilizzando AV Foundation, è possibile riprodurre, acquisire e codificare i media. È una struttura piuttosto ampia e per lo scopo di questo tutorial ci concentreremo sulla parte audio. Nello specifico, useremo il AVAudioPlayer
classe per riprodurre file MP3.
Ho fornito un progetto iniziale con tutte le azioni e le prese già configurate e con i metodi appropriati estrapolati. Anche le classi utilizzate dal progetto sono già state eliminate, così possiamo entrare nel codice. Puoi scaricare il progetto iniziale da GitHub.
Prima di poter utilizzare AV Foundation, devi collegare il progetto al framework. Nel Project Navigator, assicurati che il tuo progetto sia selezionato. Sotto il Generale scheda, vai a Quadri e biblioteche collegati e da lì scegli AVFoundation.framework.
FileReader
ClasseNel progetto iniziale, troverai un file chiamato FileReader.swift. Apri questo file per vederne il contenuto.
importare la classe UIKit FileReader: NSObject
Questo è uno stub semplice della classe che useremo per leggere i file dal disco. Da esso eredita NSObject
. Implementeremo un metodo, readFiles
, quale sarà un metodo di tipo. I metodi Type consentono di chiamare un metodo sulla classe stessa, il tipo, al contrario di un'istanza della classe. Di seguito è l'implementazione del readFiles
metodo.
class func readFiles () -> [String] return NSBundle.mainBundle (). pathsForResourcesOfType ("mp3", inDirectory: nil) as! [Stringa]
Il pacchetto principale contiene il codice e le risorse per il tuo progetto, ed è qui che troveremo gli MP3. Usiamo il metodo pathsForResourcesOfType (_: inDirectory :)
metodo, che restituisce una matrice contenente i nomi di percorso per il tipo di risorsa specificato. In questo caso, stiamo cercando il tipo "Mp3"
. Perché non siamo interessati a una directory specifica, passiamo zero
.
Questa classe sarà utilizzata da Lettore mp3
classe, su cui lavoreremo successivamente.
Lettore mp3
ClasseAvanti, aperto MP3Player.swift e vedere il suo contenuto.
import UIKit import AVFoundation class MP3Player: NSObject, AVAudioPlayerDelegate
Si noti che stiamo adottando il AVAudioPlayerDelegate
protocollo. Questo protocollo dichiara un numero di metodi utili, uno dei quali è audioPlayerDidFinishPlaying (_: con successo :)
. Implementando il audioPlayerDidFinishPlaying (_: con successo :)
metodo, verremo avvisati al termine della riproduzione dell'audio.
Aggiungi il seguente a MP3Player.swift.
class MP3Player: NSObject, AVAudioPlayerDelegate var player: AVAudioPlayer? var currentTrackIndex = 0 tracce var: [String] = [String] ()
Il giocatore
la proprietà sarà un'istanza del AVAudioPlayer
classe, che useremo per riprodurre, mettere in pausa e fermare gli MP3. Il currentTrackIndex
variabile tiene traccia di quale MP3 è attualmente in riproduzione. Finalmente, il brani
variabile sarà una matrice dei percorsi all'elenco di MP3 inclusi nel pacchetto dell'applicazione.
dentro
override init () tracks = FileReader.readFiles () super.init () queueTrack ();
Durante l'inizializzazione, invochiamo il FileReader
'S readFiles
metodo per recuperare i percorsi degli MP3 e memorizzare questo elenco in brani
array. Poiché questo è un inizializzatore designato, dobbiamo chiamare il dentro
metodo della superclasse. Infine, chiamiamo queueTrack
, che scriverò in seguito.
queueTrack
Aggiungi la seguente implementazione per queueTrack
metodo per il Lettore mp3
classe.
func queueTrack () if (player! = nil) player = nil var error: NSError? let url = NSURL.fileURLWithPath (tracce [currentTrackIndex] as String) player = AVAudioPlayer (contentsOfURL: url, error: & error) se let hasError = error // SHOW ALERT O SOMETHING else player? .delegate = self player ?. prepareToPlay ()
Perché creeremo una nuova istanza AVAudioPlayer
Ogni volta che viene chiamato questo metodo, facciamo un po 'di pulizie impostando giocatore
a zero
.
Dichiariamo un facoltativo NSError
e una costante url
. Invochiamo fileURLWithPath (_ :)
per recuperare il percorso verso l'attuale MP3 e memorizzarne il valore url
. Stiamo passando il brani
array come parametro usando currentTrackIndex
come pedice. Ricorda che l'array delle tracce contiene i percorsi degli MP3, non un riferimento ai file MP3 stessi.
Per istanziare il giocatore
, noi passiamo il url
costante e errore
variabile nel AVAudioPlayer
l'inizializzatore. Se l'inizializzazione dovesse fallire, il errore
la variabile è popolata con una descrizione dell'errore.
Se non riscontriamo un errore, impostiamo il delegato del giocatore su se stesso
e invoca il prepareToPlay
metodo sul giocatore. Il prepareToPlay
metodo precarica i buffer e acquisisce l'hardware audio, che riduce al minimo qualsiasi ritardo durante la chiamata giocare
metodo.
giocare
Il giocare
il metodo controlla prima se l'audio sta già riproducendo o meno controllando il nome corretto giocando
proprietà. Se l'audio non viene riprodotto, richiama il giocare
metodo del giocatore
proprietà.
func play () if player? .playing == false player? .play ()
Stop
Il Stop
il metodo controlla innanzitutto se il lettore audio sta già suonando. Se lo è, invoca il Stop
metodo e imposta il ora attuale
proprietà a 0. Quando invochi il Stop
metodo, interrompe semplicemente l'audio. Non ripristina l'audio all'inizio, ecco perché è necessario farlo manualmente.
func stop () if player? .playing == true player? .stop () player? .currentTime = 0
pausa
Proprio come il Stop
metodo, prima controlliamo per vedere se il lettore audio sta giocando. Se lo è, invochiamo il pausa
metodo.
func pause () if player? .playing == true player? .pause ()
prossima canzone
Il nextSong (_: Bool)
il metodo accoda il brano successivo e, se il lettore sta suonando, suona quella canzone. Non vogliamo che il brano successivo venga riprodotto se il lettore è in pausa. Tuttavia, questo metodo viene anche chiamato quando una canzone termina la riproduzione. In tal caso, vogliamo suonare la canzone successiva, che è il parametro songFinishedPlaying
è per.
func nextSong (songFinishedPlaying: Bool) var playerWasPlaying = false se player? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex ++ se currentTrackIndex> = tracks.count currentTrackIndex = 0 queueTrack () se playerWasPlaying | | songFinishedPlaying player? .play ()
Il playerWasPlaying
variabile è usata per dire se il giocatore stava giocando o meno quando questo metodo è stato invocato. Se la canzone stava suonando, invochiamo il Stop
metodo sul giocatore
e impostare playerWasPlaying
a vero
.
Successivamente, incrementiamo il currentTrackIndex
e controlla se è maggiore o uguale a tracks.count
. Il contare
la proprietà di un array ci fornisce il numero totale di elementi nell'array. Dobbiamo essere sicuri di non provare ad accedere ad un elemento che non esiste nel brani
array. Per evitare ciò, abbiamo impostato currentTrackIndex
torna al primo elemento dell'array se questo è il caso.
Infine, invochiamo queueTrack
per preparare il brano successivo e suonare quella canzone, se necessario playerWasPlaying
o songFinishedPlaying
è vero
.
previousSong
Il previousSong
metodo funziona molto simile a prossima canzone
. L'unica differenza è che decrementiamo il currentTrackIndex
e controlla se è uguale a 0. Se lo è, lo impostiamo sull'indice dell'ultimo elemento dell'array.
func previousSong () var playerWasPlaying = false se player? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex-- se currentTrackIndex < 0 currentTrackIndex = tracks.count - 1 queueTrack() if playerWasPlaying player?.play()
Utilizzando entrambi i prossima canzone
e previousSong
metodi, siamo in grado di scorrere tutti gli MP3 e ricominciare da capo quando raggiungiamo l'inizio o la fine dell'elenco.
getCurrentTrackName
Il getCurrentTrackName
metodo ottiene il nome del MP3 senza l'estensione.
func getCurrentTrackName () -> String let trackName = tracks [currentTrackIndex] .lastPathComponent.stringByDeletingPathExtension return trackName
Otteniamo un riferimento a qualunque sia l'attuale MP3 utilizzando tracce [currentTrackIndex]
. Ricorda, tuttavia, che questi sono i percorsi degli MP3 e non i file stessi. I percorsi sono piuttosto lunghi, perché è il percorso completo per i file MP3.
Sulla mia macchina, ad esempio, il primo elemento del brani
array è uguale a "/Users/jamestyner/Library/Developer/CoreSimulator/Devices/80C8CD34-22AE-4F00-862E-FD41E2D8D6BA/data/Containers/Bundle/Application/3BCF8543-BA1B-4997-9777-7EC56B1C4348/MP3Player.app/Lonesome Road Blues.mp3"Questo percorso sarebbe diverso su un dispositivo reale, naturalmente.
Abbiamo una grande stringa che contiene il percorso per l'MP3, ma vogliamo solo il nome dello stesso MP3. Il NSString
la classe definisce due proprietà che possono aiutarci. Come suggerisce il nome, il lastPathComponent
proprietà restituisce l'ultimo componente di un percorso. Come avrai intuito, il stringByDeletingPathExtension
proprietà rimuove l'estensione.
getCurrentTimeAsString
Il getCurrentTimeAsString
il metodo usa il ora attuale
proprietà del giocatore
istanza e la restituisce come una stringa leggibile dall'uomo (ad es., 01:02).
func getCurrentTimeAsString () -> String var seconds = 0 var minuti = 0 se let time = player? .currentTime seconds = Int (tempo)% 60 minutes = (Int (tempo) / 60)% 60 return String (formato : "% 0.2d:% 0.2d", minuti, secondi)
Il ora attuale
la proprietà è di tipo NSTimeInterval
, che è solo un typealias
per un Doppio
. Usiamo un po 'di matematica per ottenere il secondi
e minuti
, assicurandoci di convertirci tempo
ad Int
dal momento che abbiamo bisogno di lavorare con numeri interi. Se non si ha familiarità con l'operatore rimanente (%), trova il resto dopo la divisione di un numero con un altro. Se la tempo
la variabile era uguale a 65, poi secondi
sarebbe uguale a 5 perché stiamo usando 60.
getProgress
Il getProgress
il metodo è usato dal UIProgressView
istanza per dare un'indicazione della quantità di MP3 riprodotta. Questo progresso è rappresentato da un valore da 0.0 a 1.0 come un Galleggiante
.
func getProgress () -> Float var theCurrentTime = 0.0 var theCurrentDuration = 0.0 se let currentTime = player? .currentTime, duration = player? .duration theCurrentTime = currentTime theCurrentDuration = duration return Float (theCurrentTime / theCurrentDuration)
Per ottenere questo valore, dividiamo il giocatore
'S ora attuale
proprietà dal giocatore
'S durata
proprietà, memorizziamo questi valori nelle variabili theCurrentTime
e theCurrentDuration
. Piace ora attuale
, il durata
la proprietà è di tipo NSTimeInterval
e rappresenta la durata della canzone in secondi.
setVolume
Il setVolume (_: Float)
il metodo invoca il setVolume
metodo del giocatore
esempio.
func setVolume (volume: Float) player? .volume = volume
audioPlayerDidFinishPlaying (_: con successo :)
Il audioPlayerDidFinishPlaying (_: con successo :)
il metodo è un metodo di AVAudioPlayerDelegate
protocollo. Questo metodo prende come parametri il AVAudioPlayer
istanza e un booleano. Il booleano è impostato su vero
se il lettore audio ha finito di suonare la canzone corrente.
func audioPlayerDidFinishPlaying (player: AVAudioPlayer, flag successfully: Bool) if flag == true nextSong (true)
Se la canzone ha terminato con successo la riproduzione, chiamiamo il prossima canzone
metodo, passando dentro vero
dal momento che la canzone ha terminato di suonare da sola.
Questo completa il Lettore mp3
classe. Lo rivedremo un po 'più tardi, dopo aver implementato le azioni del ViewController
classe.
ViewController
ClasseAperto ViewController.swift e vedere il suo contenuto.
mport UIKit import AVFoundation class ViewController: UIViewController var mp3Player: MP3Player? var timer: NSTimer? @IBOutlet weak var trackName: UILabel! @IBOutlet weak var trackTime: UILabel! @IBOutlet weak var progressBar: UIProgressView! override func viewDidLoad () super.viewDidLoad () @IBAction func playSong (mittente: AnyObject) @IBAction func stopSong (mittente: AnyObject) @IBAction func pauseSong (mittente: AnyObject) @IBAction func playNextSong ( mittente: AnyObject) @IBAction func setVolume (mittente: UISlider) @IBAction func playPreviousSong (mittente: AnyObject) override func didReceiveMemoryWarning () super.didReceiveMemoryWarning () // Elimina le risorse che possono essere ricreate.
Il lettore mp3
variabile è un'istanza di Lettore mp3
classe che abbiamo implementato in precedenza. Il Timer
la variabile verrà utilizzata per aggiornare il file TrackTime
e barra di avanzamento
visualizzazioni ogni secondo.
Nei prossimi passi, implementeremo le azioni del ViewController
classe. Ma prima, dovremmo istanziare il Lettore mp3
esempio. Aggiorna l'implementazione di viewDidLoad
metodo come mostrato di seguito.
override func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player ()
playSong (_: AnyObject)
Inserisci quanto segue in playSong (_: AnyObject)
metodo.
@IBAction func playSong (mittente: AnyObject) mp3Player? .Play ()
In questo metodo, invochiamo il giocare
metodo sul lettore mp3
oggetto. Siamo al punto in cui possiamo iniziare a testare l'app ora. Esegui l'app e premi il pulsante di riproduzione. La canzone dovrebbe iniziare a suonare.
stopSong (_: AnyObject)
Il stopSong (_: AnyObject)
metodo richiama il metodo stop sul lettore mp3
oggetto.
@IBAction func stopSong (mittente: AnyObject) mp3Player? .Stop ()
Esegui nuovamente l'app e tocca il pulsante Riproduci. Ora dovresti essere in grado di interrompere la canzone toccando il pulsante stop.
pauseSong (_: AnyObject)
Come avrai intuito, il pauseSong (_: AnyObject)
il metodo invoca il pausa
metodo sul lettore mp3
oggetto.
@IBAction func pauseSong (mittente: AnyObject) mp3Player? .Pause ()
playNextSong (_: AnyObject)
IBAction func playNextSong (mittente: AnyObject) mp3Player? .NextSong (false)
Nel playNextSong (_: AnyObject)
, invochiamo il prossima canzone
metodo sul lettore mp3
oggetto. Nota che passiamo falso
come parametro, perché la canzone non ha terminato di suonare da sola. Stiamo iniziando manualmente il brano successivo premendo il pulsante successivo.
previousSong (_: AnyObject)
@IBAction func playPreviousSong (mittente: AnyObject) mp3Player? .PreviousSong ()
Come puoi vedere, l'implementazione di previousSong (_: AnyObject)
il metodo è molto simile a quello di nextSong (_: AnyObject)
. Tutti i pulsanti del lettore MP3 dovrebbero essere funzionali ora. Se non hai ancora provato l'app, ora sarebbe il momento giusto per assicurarti che tutto funzioni come previsto.
setVolume (_: UISlider)
Il setVolume (_: UISlider)
il metodo invoca il setVolume
metodo sul lettore mp3
oggetto. La proprietà del volume è di tipo Galleggiante
. Il valore varia da 0.0 a 1.0. Il UISlider
oggetto è impostato con 0.0 come il suo valore minimo e 1.0 come il suo valore massimo.
@IBAction func setVolume (mittente: UISlider) mp3Player? .SetVolume (sender.value)
Esegui l'app ancora una volta e gioca con il cursore del volume per verificare che tutto funzioni correttamente.
startTimer
Il startTimer
il metodo istanzia un nuovo NSTimer
esempio.
func startTimer () timer = NSTimer.scheduledTimerWithTimeInterval (1.0, target: self, selector: Selector ("updateViewsWithTimer:"), userInfo: nil, ripetizioni: true)
Il scheduledTimerWithTimeInterval (_: target: selettore: UserInfo: ripete :)
l'inizializzatore prende come parametri il numero di secondi tra l'accensione del timer, l'oggetto a cui chiamare un metodo su specificato da selettore
, il metodo che viene chiamato quando scatta il timer, un optional userInfo
dizionario e se il timer si ripete o meno fino a quando non viene invalidato.
Stiamo usando un metodo chiamato updateViewsWithTimer (_: NSTimer)
come selettore, quindi lo creeremo in seguito.
updateViewsWithTimer (_: NSTimer)
Il updateViewsWithTimer (_: NSTimer)
metodo chiama il updateViews
metodo, che implementeremo nel passaggio successivo.
func updateViewsWithTimer (theTimer: NSTimer) updateViews ()
updateViews
Il updateViews
metodo aggiorna il TrackTime
e barra di avanzamento
visualizzazioni.
func updateViews () trackTime.text = mp3Player? .getCurrentTimeAsString () se let progresso = mp3Player? .getProgress () progressBar.progress = progress
Il testo
proprietà di TrackTime
è aggiornato con il ora attuale
proprietà, formattata come stringa invocando il getCurrentTimeAsString
metodo. Dichiariamo una costante progresso
usando il lettore mp3
'S getProgress
metodo e impostare progressBar.progress
usando quella costante.
Ora dobbiamo chiamare il startTimer
metodo nei luoghi appropriati. Abbiamo bisogno di avviare il timer nel playSong (_: AnyObject)
metodo, il playNextSong (_: AnyObject)
metodo e il playPreviousSong (_: AnyObject)
metodo.
@IBAction func playSong (mittente: AnyObject) mp3Player? .Play () startTimer ()
@IBAction func playNextSong (mittente: AnyObject) mp3Player? .NextSong (false) startTimer ()
@IBAction func playPreviousSong (mittente: AnyObject) mp3Player? .PreviousSong () startTimer ()
Dobbiamo anche fermare il Timer
quando vengono premuti i pulsanti pausa e stop. Puoi fermare il Timer
oggetto invocando il infirmare
metodo sul NSTimer
esempio.
@IBAction func stopSong (mittente: AnyObject) mp3Player? .Stop () updateViews () timer? .Invalidate ()
@IBAction func pauseSong (mittente: AnyObject) mp3Player? .Pause () timer? .Invalidate ()
setTrackName
Il setTrackName
il metodo imposta il testo
proprietà di trackname
invocando getCurrentTrackName
sul lettore mp3
oggetto.
func setTrackName () trackName.text = mp3Player? .getCurrentTrackName ()
setupNotificationCenter
Quando una canzone finisce di suonare, dovrebbe mostrare automaticamente il nome del brano successivo e iniziare a suonare quella canzone. Inoltre, quando l'utente preme i pulsanti play, next o previous, il pulsante setTrackName
il metodo dovrebbe essere invocato. Il posto ideale per farlo è il queueTrack
metodo del Lettore mp3
classe.
Abbiamo bisogno di un modo per avere il Lettore mp3
la classe dice il ViewController
classe per invocare il setTrackName
metodo. Per farlo, useremo il NSNotificationCenter
classe. Il centro di notifica fornisce un modo per trasmettere informazioni attraverso un programma. Registrandosi come osservatore con il centro di notifica, un oggetto può ricevere queste trasmissioni ed eseguire un'operazione. Un altro modo per eseguire questa operazione sarebbe utilizzare il modello di delega.
Aggiungi il seguente metodo al ViewController
classe.
func setupNotificationCenter () NSNotificationCenter.defaultCenter (). addObserver (self, selector: "setTrackName", nome: "SetTrackNameText", oggetto: nil)
Prima otteniamo un riferimento al centro di notifica predefinito. Quindi invochiamo il addObserver (_: selettore: Nome: oggetto :)
metodo sul centro di notifica. Questo metodo accetta quattro parametri:
se stesso
in questo casoEntrando zero
come ultimo argomento, ascoltiamo ogni notifica che ha un nome SetTrackNameText.
Ora dobbiamo chiamare questo metodo nel controller della vista viewDidLoad
metodo.
override func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter ()
Per pubblicare la notifica, invochiamo il postNotificationName (_: oggetto :)
metodo sul centro di notifica predefinito. Come ho detto prima, lo faremo nel queueTrack
metodo del Lettore mp3
classe. Aperto MP3Player.swift e aggiorna il queueTrack
metodo come mostrato di seguito.
func queueTrack () if (player! = nil) player = nil var error: NSError? let url = NSURL.fileURLWithPath (tracce [currentTrackIndex] as String) player = AVAudioPlayer (contentsOfURL: url, error: & error) se let hasError = error // SHOW ALERT O SOMETHING else player? .delegate = self player ?. prepareToPlay () NSNotificationCenter.defaultCenter (). postNotificationName ("SetTrackNameText", object: nil)
Se provi l'app ora e fai suonare una canzone fino in fondo, dovrebbe iniziare a suonare automaticamente il brano successivo. Ma potresti chiederti perché il nome del brano non viene visualizzato durante la prima canzone. Il dentro
metodo del Lettore mp3
la classe chiama il queueTrack
metodo, ma poiché non ha terminato l'inizializzazione, non ha alcun effetto.
Tutto quello che dobbiamo fare è chiamare manualmente il setTrackName
metodo dopo aver inizializzato il lettore mp3
oggetto. Aggiungi il seguente codice al viewDidLoad
metodo in ViewController.swift.
override func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter () setTrackName () updateViews ()
Noterai che ho anche chiamato il updateViews
metodo. In questo modo, il giocatore mostra un tempo di 00:00 all'inizio. Se testate l'app ora, dovreste avere un lettore MP3 pienamente funzionante.
Questo è stato un tutorial piuttosto lungo, ma ora hai un lettore MP3 funzionale da costruire ed espandere. Un suggerimento è quello di consentire all'utente di scegliere un brano da suonare implementando un UITableView
sotto il giocatore. Grazie per la lettura e spero che tu abbia imparato qualcosa di utile.