AV Foundation este un cadru pentru lucrul cu medii audio și vizuale pe iOS și OSX. Folosind AV Foundation, puteți reda, captura și codifica suporturi media. Este un cadru destul de extins și în scopul acestui tutorial ne vom concentra pe partea audio. În mod specific, vom folosi AVAudioPlayer
clasă pentru a reda fișiere MP3.
Am oferit un proiect demarat, care are toate acțiunile și punctele de desfacere deja configurate și cu metodele adecvate stubate. Clasele pe care le folosește proiectul, sunt deja stubate, astfel încât să ne putem arunca cu grijă în cod. Puteți descărca proiectul starter de la GitHub.
Înainte de a putea utiliza Fundația AV, trebuie să conectați proiectul la cadru. În Project Navigator, asigurați-vă că proiectul dvs. este selectat. Sub General , mergeți la Cadrele și bibliotecile asociate și de acolo alegeți AVFoundation.framework.
FileReader
ClasăÎn proiectul de pornire, veți găsi un fișier numit FileReader.swift. Deschideți acest fișier pentru a vedea conținutul acestuia.
importați clasa UIKit FileReader: NSObject
Acesta este un simplu stub al clasei pe care o vom folosi pentru a citi fișierele de pe disc. Moșteneste de la NSObject
. Vom implementa o metodă, readFiles
, care va fi o metodă de tip. Tipurile de metode vă permit să apelați o metodă pe clasa însăși, tipul, spre deosebire de o instanță a clasei. Mai jos este implementarea readFiles
metodă.
class func readFiles () -> [String] returnați NSBundle.mainBundle () pathsForResourcesOfType ("mp3", inDirectory: nil) ca! [String]
Banda principală conține codul și resursele pentru proiectul dvs. și aici găsim MP3-urile. Folosim metoda pathsForResourcesOfType (_: inDirectory :)
, care returnează o matrice care conține numele de cale pentru tipul de resursă specificat. În acest caz, căutăm tipul "Mp3"
. Pentru că nu suntem interesați de un anumit director, intrăm zero
.
Această clasă va fi utilizată de către Mp3 player
clasa, pe care vom lucra la următoarea.
Mp3 player
ClasăÎn continuare, deschideți-vă MP3Player.swift și vizualizați conținutul acestuia.
import import UIKit clasă AVFoundation MP3Player: NSObject, AVAudioPlayerDelegate
Observați că adoptăm AVAudioPlayerDelegate
protocol. Acest protocol declară o serie de metode utile, dintre care una este audioPlayerDidFinishPlaying (_: cu succes :)
. Prin implementarea audioPlayerDidFinishPlaying (_: cu succes :)
, vom fi anunțați când sunetul a terminat de redat.
Adăugați următoarele la MP3Player.swift.
clasa MP3Player: NSObject, AVAudioPlayerDelegate var player: AVAudioPlayer? var currentTrackIndex = 0 piese var: [String] = [String] ()
jucător
proprietate va fi o instanță a AVAudioPlayer
clasa pe care o vom folosi pentru a juca, a întrerupe și a opri MP3-urile. currentTrackIndex
variabila ține evidența jocurilor MP3 care se joacă în prezent. În cele din urmă, piese
variabila va fi o serie de căi spre lista de MP3-uri care sunt incluse în pachetul aplicației.
init
suprascrie init () tracks = FileReader.readFiles () super.init () queueTrack ();
În timpul inițializării, invocăm FileReader
„s readFiles
pentru a prelua căile MP3 și pentru a stoca această listă în piese
matrice. Deoarece acesta este un inițializator desemnat, trebuie să sunăm init
metoda superclasei. În cele din urmă, sunăm queueTrack
, pe care o vom scrie în continuare.
queueTrack
Adăugați următoarea implementare pentru queueTrack
metoda pentru a Mp3 player
clasă.
func queueTrack () if (player! = nil) player = nil var eroare: NSError? lasă url = NSURL.fileURLWithPath (urmărește [currentTrackIndex] ca String) player = AVAudioPlayer (contentsOfURL: url, eroare: & eroare) ifError = eroare // SHOW ALERT SAU NICIODATĂ altceva player? .delegate = self player? prepareToPlay ()
Pentru că vom institui un nou AVAudioPlayer
de exemplu, de fiecare dată când se numește această metodă, facem puțină gospodărie prin setare jucător
la zero
.
Declarăm un opțional NSError
și o constantă URL-ul
. Noi invocăm fileURLWithPath (_ :)
pentru a prelua calea către MP3-ul curent și pentru a stoca valoarea în URL-ul
. Noi trecem piese
array ca parametru folosind currentTrackIndex
ca indicele. Amintiți-vă că matricea pieselor conține căile spre MP3, nu o referință la fișierele MP3.
Pentru a instantiza jucător
, noi trecem URL-ul
constantă și eroare
variabilă în AVAudioPlayer
a inițializatorului. Dacă inițializarea se întâmplă să eșueze, eroare
variabila este populate cu o descriere a erorii.
Dacă nu întâlnim o eroare, setăm delegatul jucătorului de sine
și invocați prepareToPlay
pe player. prepareToPlay
metoda preloads tampoanele și achiziționează hardware audio, care minimizează orice întârziere atunci când apelează Joaca
metodă.
Joaca
Joaca
metoda verifică mai întâi pentru a vedea dacă audio-ul este deja redat sau nu prin verificarea numelui potrivit joc
proprietate. Dacă sunetul nu se redă, acesta invocă Joaca
metodă a jucător
proprietate.
func play () dacă jucătorul? .playing == false player? .play ()
Stop
Stop
metoda verifică mai întâi dacă playerul audio este deja redat. Dacă este, invocă Stop
și stabilește metoda ora curentă
proprietate la 0. Când invocați Stop
metoda, aceasta oprește doar sunetul. Nu restabilește sunetul la început, motiv pentru care trebuie să îl facem manual.
func stop () dacă jucătorul? .playing == true player? .stop () player? .currentTime = 0
pauză
La fel ca și Stop
, verificăm mai întâi să vedem dacă redarea audio este redată. Dacă este, invocăm pauză
metodă.
functie pauza () daca jucatorul? .playing == true player? .pause ()
Următorul cântec
nextSong (_: Bool)
metoda cade în sus cântecul următor și, dacă jucătorul joacă, cânte cântecul respectiv. Nu vrem ca următoarea melodie să fie redată dacă playerul este întrerupt. Cu toate acestea, această metodă este, de asemenea, numită atunci când o melodie termină să se joace. În acest caz, dorim să jucăm următorul cântec, care este parametrul songFinishedPlaying
este pentru.
func nextSong (cântecFinishedPlaying: Bool) var playerWasPlaying = false dacă jucătorul? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex ++ dacă currentTrackIndex> = tracks.count currentTrackIndex = 0 queueTrack () if playerWasPlaying | | songFinishedPlaying player? .play ()
playerWasPlaying
variabila este utilizată pentru a spune dacă jucătorul a fost sau nu jucat atunci când a fost invocată această metodă. Dacă piesa se joacă, vom invoca Stop
metoda pe jucător
și stabilit playerWasPlaying
la Adevărat
.
Apoi, noi incrementăm currentTrackIndex
și verificați dacă este mai mare sau egală cu tracks.count
. numara
proprietatea unei matrice ne dă numărul total de elemente din matrice. Trebuie să fim siguri că nu încercăm să accesăm un element care nu există în piese
matrice. Pentru a preveni acest lucru, am stabilit currentTrackIndex
înapoi la primul element al matricei, dacă este cazul.
În cele din urmă, invocăm queueTrack
pentru a primi următoarea melodie și pentru a reda melodia respectivă, dacă vreți playerWasPlaying
sau songFinishedPlaying
este Adevărat
.
previousSong
previousSong
metoda funcționează foarte asemănătoare Următorul cântec
. Singura diferență este că noi decrementăm currentTrackIndex
și verificați dacă este egal cu 0. Dacă este, îl setăm la indexul ultimului element din matrice.
func previousSong () var playerWasPlaying = false dacă jucătorul? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex-- dacă curentTrackIndex < 0 currentTrackIndex = tracks.count - 1 queueTrack() if playerWasPlaying player?.play()
Utilizând ambele Următorul cântec
și previousSong
metode, suntem capabili de a naviga prin toate MP3-urile și de a începe peste când ajungem la începutul sau la sfârșitul listei.
getCurrentTrackName
getCurrentTrackName
metoda primește numele fișierului MP3 fără extensie.
func getCurrentTrackName () -> String lasa trackName = piese [currentTrackIndex] .lastPathComponent.stringByDeletingPathExtension return trackName
Avem o referință la ceea ce folosește MP3-ul curent piese [currentTrackIndex]
. Amintiți-vă, totuși, că acestea sunt căile către MP3-uri și nu la fișierele în sine. Calele sunt destul de lungi, pentru că este calea completă către fișierele MP3.
Pe mașina mea, de exemplu, primul element al mașinii piese
array este egal cu "/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"Această cale ar fi diferită pe un dispozitiv real, desigur.
Avem un șir mare care conține calea către MP3, dar vrem doar numele MP3-ului în sine. NSString
clasa definește două proprietăți care ne pot ajuta. După cum sugerează și numele, lastPathComponent
proprietatea returnează ultima componentă a unei căi. După cum probabil ați ghicit, stringByDeletingPathExtension
proprietatea elimină extensia.
getCurrentTimeAsString
getCurrentTimeAsString
utilizează metoda ora curentă
proprietate a jucător
instanță și o returnează ca un șir citit de om (de ex., 01:02).
funcția get () = var = secunde = var secunde = 0 var minute = 0 dacă timpul = player =. : "% 0.2d:% 0.2d", minute, secunde)
ora curentă
proprietatea este de tip NSTimeInterval
, care este doar o typealias
Pentru o Dubla
. Folosim niște matematici pentru a obține secunde
și minute
, asigurându-ne că vom converti timp
la un Int
deoarece trebuie să lucrăm cu numere întregi. Dacă nu sunteți familiarizat cu operatorul rămas (%), acesta găsește restul după divizarea unui număr de altul. În cazul în care timp
variabila era egală cu 65, atunci secunde
ar fi egal cu 5 pentru că noi folosim 60.
getProgress
getProgress
metoda este folosită de UIProgressView
exemplu pentru a da o indicație despre cât de mult a jucat MP3-ul. Acest progres este reprezentat de o valoare de la 0.0 la 1.0 ca Pluti
.
func getProgress () -> Float var theCurrentTime = 0.0 var theCurrentDuration = 0.0 dacă permite curentTime = player? .currentTime, duration = player? .duration theCurrentTime = currentTime theCurrentDuration = duration return Float (CurrentTime /CurrentDuration)
Pentru a obține această valoare, împărțim jucător
„s ora curentă
proprietate de către jucător
„s durată
proprietăți, stocăm aceste valori în variabile theCurrentTime
și theCurrentDuration
. Ca ora curentă
, durată
proprietatea este de tip NSTimeInterval
și reprezintă durata cantecului în câteva secunde.
setVolume
setVolume (_: float)
metoda invocă setVolume
metodă a jucător
instanță.
func setVolume (volum: Float) player? .volume = volume
audioPlayerDidFinishPlaying (_: cu succes :)
audioPlayerDidFinishPlaying (_: cu succes :)
metoda este o metodă a AVAudioPlayerDelegate
protocol. Această metodă ia ca parametri AVAudioPlayer
instanță și booleană. Booleanul este setat la Adevărat
dacă playerul audio a terminat de redat melodia curentă.
func audioPlayerDidFinishPlaying (player: AVAudioPlayer, cu succes flag: Bool) if flag == true nextSong (true)
Dacă melodia a terminat cu succes redarea, sunăm Următorul cântec
metodă, care trece Adevărat
deoarece cântecul a terminat să joace singur.
Acest lucru completează Mp3 player
clasă. O vom revizui puțin mai tîrziu, după ce am implementat acțiunile ViewController
clasă.
ViewController
ClasăDeschis ViewController.swift și vizualizați conținutul acestuia.
mport Import UIKit AVFoundation clasa ViewController: UIViewController var mp3Player: MP3Player? var timer: NSTimer? @IBOutlet slab var trackName: UILabel! @IBOutlet slab var trackTime: UILabel! @ IBOutlet slab var progresBar: UIProgressView! override function viewDidLoad () super.viewDidLoad () @IBAction func playSong (expeditor: AnyObject) @IBAction func stopSong (expeditor: AnyObject) @IBAction func pauseSong (expeditor: AnyObject) @IBAction func playNextSong expeditor: AnyObject) @IBAction func setVolume (expeditor: UISlider) @IBAction func playPreviousSong (expeditor: AnyObject) override func didReceiveMemoryWarning () super.didReceiveMemoryWarning () // Elimina orice resurse care pot fi recreate.
mp3 player
variabila este o instanță a Mp3 player
pe care am implementat-o mai devreme. timer
variabila va fi utilizată pentru a actualiza trackTime
și bara de progres
vizionează în fiecare secundă.
În următorii pași, vom implementa acțiunile ViewController
clasă. Dar, mai întâi, ar trebui să instanțiăm Mp3 player
instanță. Actualizați punerea în aplicare a viewDidLoad
așa cum se arată mai jos.
override functie viewDidLoad () super.viewDidLoad () mp3Player = MP3Player ()
playSong (_: AnyObject)
Introduceți următoarele în playSong (_: AnyObject)
metodă.
@IBAction func playSong (expeditor: AnyObject) mp3Player? .Play ()
În această metodă, invocăm Joaca
metoda pe mp3 player
obiect. Suntem într-un moment în care putem începe testarea aplicației acum. Rulați aplicația și apăsați butonul de redare. Cântecul ar trebui să înceapă să joace.
stopSong (_: AnyObject)
stopSong (_: AnyObject)
metoda invocă metoda de oprire pe mp3 player
obiect.
@IBAction func stopSong (expeditor: AnyObject) mp3Player? .Stop ()
Rulați din nou aplicația și atingeți butonul de redare. Acum ar trebui să puteți opri melodia prin atingerea butonului stop.
pauzăSong (_: AnyObject)
După cum probabil ați ghicit, pauzăSong (_: AnyObject)
metoda invocă pauză
metoda pe mp3 player
obiect.
@IBAction func pauseSong (expeditor: AnyObject) mp3Player? .Pause ()
playNextSong (_: AnyObject)
IBAction func playNextSong (expeditor: AnyObject) mp3Player? .NextSong (false)
În playNextSong (_: AnyObject)
, noi invocăm Următorul cântec
metoda pe mp3 player
obiect. Rețineți că trecem fals
ca parametru, deoarece piesa nu a terminat să joace pe cont propriu. Pornim manual următoarea melodie apăsând butonul următor.
anteriorSong (_: AnyObject)
@IBAction func playPreviousSong (expeditor: AnyObject) mp3Player? .PreviousSong ()
După cum puteți vedea, punerea în aplicare a anteriorSong (_: AnyObject)
metoda este foarte asemănătoare cu cea a lui nextSong (_: AnyObject)
. Toate butoanele playerului MP3 ar trebui să funcționeze acum. Dacă nu ați testat încă aplicația, acum ar fi un moment bun pentru a vă asigura că totul funcționează conform așteptărilor.
setVolume (_: UISlider)
setVolume (_: UISlider)
metoda invocă setVolume
metoda pe mp3 player
obiect. Proprietatea volumului este de tip Pluti
. Valoarea variază de la 0.0 la 1.0. UISlider
obiect este configurat cu 0.0 ca valoare minimă și 1.0 ca valoare maximă.
@IBAction func setVolume (expeditor: UISlider) mp3Player? .SetVolume (sender.value)
Rulați aplicația încă o dată și jucați cu glisorul de volum pentru a testa că totul funcționează corect.
startTimer
startTimer
metoda instantiates un nou NSTimer
instanță.
func startTimer () timer = NSTimer.scheduledTimerWithTimeInterval (1.0, țintă: self, selector: Selector ("updateViewsWithTimer:"), userInfo: nil, repetă: true)
scheduledTimerWithTimeInterval (_: țintă: selector: userinfo: se repetă :)
inițializatorul ia ca parametri numărul de secunde dintre arderea temporizatorului, obiectul la care se poate apela o metodă specificată de selector
, metoda care se numește când se declanșează cronometrul, o opțiune userinfo
dicționar și dacă se repetă sau nu timerul până când acesta este invalidat.
Folosim o metodă numită updateViewsWithTimer (_: NSTimer)
ca selector, așa că vom crea asta în continuare.
updateViewsWithTimer (_: NSTimer)
updateViewsWithTimer (_: NSTimer)
metoda solicită updateViews
metodă pe care o vom implementa în etapa următoare.
func updateViewsWithTimer (Timer: NSTimer) updateViews ()
updateViews
updateViews
actualizează metoda trackTime
și bara de progres
vizualizari.
func updateViews () trackTime.text = mp3Player? .getCurrentTimeAsString () dacă permiteți progresul = mp3Player? .getProgress () progressBar.progress = progress
text
proprietatea trackTime
este actualizat cu ora curentă
proprietate, formatat ca un șir prin invocarea getCurrentTimeAsString
metodă. Declarăm o constantă progres
folosind mp3 player
„s getProgress
metoda și setul progressBar.progress
folosind acea constantă.
Acum trebuie să sunăm startTimer
în locurile potrivite. Trebuie să pornim cronometrul în playSong (_: AnyObject)
metodă, playNextSong (_: AnyObject)
metoda, și playPreviousSong (_: AnyObject)
metodă.
@IBAction func playSong (expeditor: AnyObject) mp3Player? .Play () startTimer ()
@IBAction func playNextSong (expeditor: AnyObject) mp3Player? .NextSong (false) startTimer ()
@IBAction func playPreviousSong (expeditor: AnyObject) mp3Player? .PreviousSong () startTimer ()
De asemenea, trebuie să oprim timer
când sunt apăsate butoanele de întrerupere și oprire. Puteți opri timer
obiecte invocând invalida
metoda pe NSTimer
instanță.
@IBAction func stopSong (expeditor: AnyObject) mp3Player? .Stop () updateViews () timer? .Invalidate ()
@IBAction func pauseSong (expeditor: AnyObject) mp3Player? .Pause () timer? .Invalidate ()
setTrackName
setTrackName
metoda stabilește text
proprietatea trackName
invocând getCurrentTrackName
pe mp3 player
obiect.
func setTrackName () trackName.text = mp3Player? .getCurrentTrackName ()
setupNotificationCenter
Când o melodie termină să fie redată, ar trebui să afișeze automat numele următorului cântec și să înceapă să cânte melodia respectivă. De asemenea, când utilizatorul apasă butoanele de redare, următor sau anterioare, setTrackName
trebuie invocată metoda. Locul ideal pentru a face acest lucru este queueTrack
metodă a Mp3 player
clasă.
Avem nevoie de o modalitate de a avea Mp3 player
clasa spune ViewController
clasa pentru a invoca setTrackName
metodă. Pentru a face asta, vom folosi NSNotificationCenter
clasă. Centrul de notificare oferă o modalitate de difuzare a informațiilor în cadrul unui program. Prin înregistrarea ca observator la centrul de notificare, un obiect poate primi aceste emisiuni și poate efectua o operație. O altă modalitate de a îndeplini această sarcină ar fi utilizarea modelului de delegare.
Adăugați următoarea metodă la ViewController
clasă.
func setNotificationCenter () NSNotificationCenter.defaultCenter (). addObserver (auto, selector: "setTrackName", nume: "SetTrackNameText", obiect: nil)
Mai întâi obținem o referință la centrul implicit de notificare. Apoi invocăm addObserver (_: selector: Nume: obiect :)
pe centrul de notificare. Această metodă acceptă patru parametri:
de sine
în acest cazTrecând zero
ca ultimul argument, ascultăm pentru fiecare notificare care are un nume de SetTrackNameText.
Acum trebuie să apelăm această metodă în controlerul de vizualizare viewDidLoad
metodă.
override func vizualizareDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter ()
Pentru a posta notificarea, vom invoca postNotificationName (_: obiect :)
la centrul implicit de notificare. Așa cum am menționat mai devreme, vom face acest lucru în queueTrack
metodă a Mp3 player
clasă. Deschis MP3Player.swift și actualizați queueTrack
așa cum se arată mai jos.
func queueTrack () if (player! = nil) player = nil var eroare: NSError? lasă url = NSURL.fileURLWithPath (urmărește [currentTrackIndex] ca String) player = AVAudioPlayer (contentsOfURL: url, eroare: & eroare) ifError = eroare // SHOW ALERT SAU NICIODATĂ altceva player? .delegate = self player? NNotificationName ("SetTrackNameText", obiect: nil) NNotificationCenter.defaultCenter ()
Dacă testați aplicația acum și lăsați o melodie să se joace tot timpul, ar trebui să începeți să redați automat următoarea melodie. Dar s-ar putea să te întrebi de ce numele cântecului nu apare în timpul primei melodii. init
metodă a Mp3 player
clasa apeluri queueTrack
dar din moment ce nu a terminat inițializarea, nu are niciun efect.
Tot ce trebuie să facem este să sunăm manual setTrackName
după ce inițializăm mp3 player
obiect. Adăugați următorul cod la viewDidLoad
metoda în ViewController.swift.
override func vizualizareDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter () setTrackName () updateViews ()
Veți observa că am sunat și eu updateViews
metodă. În acest fel, jucătorul prezintă un timp de 0:00 la inceput. Dacă testați acum aplicația, ar trebui să aveți un MP3 player complet funcțional.
Acesta a fost un tutorial destul de lung, dar acum aveți un MP3 player funcțional pentru a construi și extinde. O sugestie este aceea de a permite utilizatorului să aleagă o melodie pe care să o joace prin implementarea unui UITableView
sub jucator. Vă mulțumim pentru lectură și sper că ați învățat ceva util.