AV Foundation er et rammeverk for å jobbe med lyd og visuelt media på iOS og OSX. Ved hjelp av AV Foundation kan du spille, fange opp og kode medie. Det er ganske omfattende rammeverk og for formålet med denne opplæringen vil vi fokusere på lyddelen. Spesielt vil vi bruke AVAudioPlayer
klassen for å spille MP3-filer.
Jeg har gitt et startprosjekt som har alle handlingene og uttakene allerede konfigurert, og med de riktige metodene stubbet ut. Klassene prosjektet bruker, er allerede stubbet ut så vel, så vi kan dykke rett inn i koden. Du kan laste ned startprosjektet fra GitHub.
Før du kan bruke AV Foundation, må du koble prosjektet mot rammen. I Prosjektnavigator, sørg for at prosjektet er valgt. Under Generell kategorien, gå til Sammenhengende rammer og biblioteker og derfra velger du AVFoundation.framework.
Filereader
KlasseI startprosjektet finner du en fil som heter FileReader.swift. Åpne denne filen for å se innholdet.
importere UIKit klasse FileReader: NSObject
Dette er en enkel stub av klassen som vi vil bruke til å lese filer fra disken. Det arver fra NSObject
. Vi vil implementere en metode, readFiles
, som vil være en type metode. Typemetoder lar deg ringe en metode på selve klassen, typen, i motsetning til en forekomst av klassen. Nedenfor er implementeringen av readFiles
metode.
class func readFiles () -> [String] return NSBundle.mainBundle (). pathsForResourcesOfType ("mp3", inDirectory: null) som! [String]
Hovedpakken inneholder koden og ressursene for prosjektet ditt, og det er her at vi finner MP3-ene. Vi bruker metoden pathsForResourcesOfType (_: inDirectory :)
metode, som returnerer en matrise som inneholder banenavnene for den angitte ressurstypen. I dette tilfellet søker vi etter type "Mp3"
. Fordi vi ikke er interessert i en bestemt katalog, passerer vi inn nil
.
Denne klassen vil bli brukt av Mp3 spiller
klassen, som vi vil jobbe med på neste.
Mp3 spiller
KlasseDeretter åpne MP3Player.swift og se innholdet.
importere UIKit import AVFoundation klasse MP3Player: NSObject, AVAudioPlayerDelegate
Legg merke til at vi vedtar AVAudioPlayerDelegate
protokoll. Denne protokollen erklærer en rekke nyttige metoder, hvorav en er audioPlayerDidFinishPlaying (_: hell :)
. Ved å implementere audioPlayerDidFinishPlaying (_: hell :)
Metode, vi vil bli varslet når lyden er ferdig med å spille.
Legg til følgende til MP3Player.swift.
klasse MP3Player: NSObject, AVAudioPlayerDelegate var spiller: AVAudioPlayer? var currentTrackIndex = 0 var spor: [String] = [String] ()
De spiller
eiendom vil være en forekomst av AVAudioPlayer
klassen, som vi vil bruke til å spille, pause og stoppe MP3-ene. De currentTrackIndex
variabel holder oversikt over hvilken MP3 som spilles. Endelig, den spor
variabel vil være en rekke stier til listen over MP3 som er inkludert i programmets bunt.
i det
overstyr init () tracks = FileReader.readFiles () super.init () queueTrack ();
Under initialisering påberoper vi oss Filereader
's readFiles
metode for å hente stiene til MP3 og lagre denne listen i spor
array. Fordi dette er en utpekt initialiserer, må vi ringe i det
metode for superklassen. Til slutt, vi ringer queueTrack
, som vi skal skrive neste.
queueTrack
Legg til følgende implementering for queueTrack
metode til Mp3 spiller
klasse.
func queueTrack () if (player! = nil) player = nil var feil: NSError? la url = NSURL.fileURLWithPath (spor [currentTrackIndex] som String) player = AVAudioPlayer (contentOfURL: url, feil: & feil) hvis la hasError = feil // SHOW ALERT ELLER ENKELT annet spiller? .delegate = selvspiller ?. prepareToPlay ()
Fordi vi vil instantiere en ny AVAudioPlayer
forekom hver gang denne metoden heter, gjør vi litt housekeeping ved å sette inn spiller
til nil
.
Vi erklærer en valgfri NSError
og en konstant url
. Vi påberoper fileURLWithPath (_ :)
for å hente banen til gjeldende MP3 og lagre verdien i url
. Vi passerer spor
array som parameter ved hjelp av currentTrackIndex
som abonnementet. Husk at sporene inneholder stiene til MP3, ikke en referanse til MP3-filene selv.
For å instantiere spiller
, vi passerer url
konstant og feil
variabel inn i AVAudioPlayer
s initialiserer. Hvis initialiseringen skjer, mislykkes den feil
variabel er fylt med en beskrivelse av feilen.
Hvis vi ikke støter på en feil, setter vi spillerens delegat til selv-
og påkalle prepareToPlay
metode på spilleren. De prepareToPlay
Metoden forlaster bufferne og kjøper lydmaskinvaren, noe som minimerer enhver lagring når du ringer til spille
metode.
spille
De spille
Metoden kontrollerer først for å se om lyden allerede spiller ved å sjekke det passende navnet spiller
eiendom. Hvis lyden ikke spiller, påkaller den spille
metode av spiller
eiendom.
func play () hvis spiller? .playing == false player? .play ()
Stoppe
De Stoppe
Metoden kontrollerer først om lydspilleren allerede spiller. Hvis det er, påkaller det Stoppe
metode og setter nåværende tid
eiendom til 0. Når du påkaller Stoppe
metode, det stopper bare lyden. Det tilbakestiller ikke lyden til begynnelsen, og derfor må vi gjøre det manuelt.
func stop () hvis spiller? .playing == sann spiller? .stop () spiller? .currentTime = 0
pause
Akkurat som Stoppe
metode, vi sjekker først for å se om lydspilleren spiller. Hvis det er, påberoper vi oss pause
metode.
func pause () hvis spilleren? .playing == true player? .pause ()
nextSong
De nextSong (_: Boolsk)
Metoden køer opp neste sang, og hvis spilleren spiller, spiller den sangen. Vi vil ikke ha den neste sangen som spilles hvis spilleren er pauset. Denne metoden kalles imidlertid også når en sang er ferdig med å spille. I så fall ønsker vi å spille den neste sangen, som er parameteren songFinishedPlaying
er for.
func nextSong (songFinishedPlaying: Bool) var playerWasPlaying = false hvis spiller? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex ++ hvis currentTrackIndex> = tracks.count currentTrackIndex = 0 køTrack () hvis playerWasPlaying | | songFinishedPlaying spiller? .play ()
De playerWasPlaying
variabel brukes til å fortelle om spilleren spilte når denne metoden ble påkalt. Hvis sangen lekte, ringer vi på Stoppe
metode på spiller
og sett playerWasPlaying
til ekte
.
Deretter øker vi currentTrackIndex
og sjekk for å se om den er større enn eller lik tracks.count
. De telle
Egenskapen til en matrise gir oss det totale antall elementer i matrisen. Vi må være sikre på at vi ikke prøver å få tilgang til et element som ikke finnes i spor
array. For å forhindre dette, setter vi inn currentTrackIndex
tilbake til det første elementet i gruppen hvis dette er tilfelle.
Til slutt påberoper vi oss queueTrack
for å få den neste sangen klar og spille den sangen hvis heller playerWasPlaying
eller songFinishedPlaying
er ekte
.
previousSong
De previousSong
Metoden fungerer veldig lik nextSong
. Den eneste forskjellen er at vi reduserer currentTrackIndex
og sjekk om det er lik 0. Hvis det er, setter vi det til indeksen for det siste elementet i matrisen.
func previousSong () var playerWasPlaying = false hvis spiller? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex - hvis currentTrackIndex < 0 currentTrackIndex = tracks.count - 1 queueTrack() if playerWasPlaying player?.play()
Ved å benytte begge nextSong
og previousSong
metoder, vi er i stand til å sykle gjennom alle MP3-ene og starte over når vi kommer til begynnelsen eller slutten av listen.
getCurrentTrackName
De getCurrentTrackName
Metoden får navnet på MP3 uten utvidelsen.
func getCurrentTrackName () -> String la trackName = spor [currentTrackIndex] .lastPathComponent.stringByDeletingPathExtension return trackName
Vi får en referanse til hva den nåværende MP3 er ved å bruke spor [currentTrackIndex]
. Husk imidlertid at disse er stiene til MP3-ene og ikke selve filene selv. Banene er ganske lange, fordi det er den fulle veien til MP3-filene.
På min maskin, for eksempel, det første elementet i spor
array er lik "/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". Denne banen ville være annerledes på en faktisk enhet selvfølgelig.
Vi har en stor streng som inneholder banen til MP3, men vi vil bare ha navnet på selve MP3-en. De NSString
Klassen definerer to egenskaper som kan hjelpe oss. Som navnet tilsier, er det lastPathComponent
Egenskapen returnerer den siste komponenten av en bane. Som du kanskje har gjettet, stringByDeletingPathExtension
Egenskapen fjerner forlengelsen.
getCurrentTimeAsString
De getCurrentTimeAsString
Metoden bruker nåværende tid
eiendom av spiller
forekomst og returnerer den som en menneskelig lesbar streng (f.eks., 01:02).
func getCurrentTimeAsString () -> String var sekunder = 0 var minutter = 0 hvis la tid = spiller? .currentTime sekunder = Int (tid)% 60 minutter = (Int (tid) / 60)% 60 Return String : "% 0.2d:% 0.2d", minutter, sekunder)
De nåværende tid
Eiendommen er av typen NSTimeInterval
, som bare er en typealias
for en Dobbelt
. Vi bruker litt matte for å få sekunder
og minutter
, sørger for at vi konverterer tid
til en int
siden vi trenger å jobbe med hele tall. Hvis du ikke er kjent med resten av operatøren (%), finner den resten etter oppdeling av ett nummer av en annen. Hvis tid
variabel var lik 65, deretter sekunder
ville være lik 5 fordi vi bruker 60.
getProgress
De getProgress
Metoden brukes av UIProgressView
eksempel for å gi en indikasjon på hvor mye MP3 har spilt. Denne fremgangen er representert med en verdi fra 0.0 til 1.0 som en Flyte
.
funksjon
For å få denne verdien deler vi spiller
's nåværende tid
eiendom ved spiller
's varighet
eiendom, lagrer vi disse verdiene i variablene theCurrentTime
og theCurrentDuration
. Som nåværende tid
, de varighet
Eiendommen er av typen NSTimeInterval
og det representerer varigheten av sangen i sekunder.
setVolume
De setVolume (_: Float)
metode påberoper seg setVolume
metode av spiller
forekomst.
func setVolume (volum: Float) spiller? .volume = volum
audioPlayerDidFinishPlaying (_: hell :)
De audioPlayerDidFinishPlaying (_: hell :)
Metode er en metode for AVAudioPlayerDelegate
protokoll. Denne metoden tar som parametere AVAudioPlayer
eksempel og en boolsk. Den boolske er satt til ekte
hvis lydspilleren er ferdig med å spille den nåværende sangen.
func audioPlayerDidFinishPlaying (spiller: AVAudioPlayer, vellykket flagg: Bool) hvis flagg == true nextSong (true)
Hvis sangen er ferdig med å spille, kaller vi nextSong
metode, passerer inn ekte
siden sangen avsluttet å spille alene.
Dette fullfører Mp3 spiller
klasse. Vi vil revidere det litt senere, etter å ha gjennomført handlingene til ViewController
klasse.
ViewController
KlasseÅpen ViewController.swift og se innholdet.
mport UIKit import AVFoundation klasse ViewController: UIViewController var mp3Player: MP3Player? var timer: NSTimer? @IBOutlet svak var spornavn: UILabel! @IBOutlet svak var trackTime: UILabel! @IBOutlet svak var fremgangBar: UIProgressView! overstyr func viewDidLoad () super.viewDidLoad () @IBAction func playSong (sender: AnyObject) @IBAction func stopSong (sender: AnyObject) @IBAction func pauseSong (sender: AnyObject) @IBAction func playNextSong avsender: AnyObject) @IBAction func setVolume (sender: UISlider) @IBAction func playPreviousSong (sender: AnyObject) overstyr func didReceiveMemoryWarning () super.didReceiveMemoryWarning () // Kast bort eventuelle ressurser som kan gjenopprettes.
De mp3 spiller
variabel er en forekomst av Mp3 spiller
klasse vi implementerte tidligere. De tidsur
variabel vil bli brukt til å oppdatere Tracktime
og ProgressBar
visninger hvert sekund.
I de neste trinnene vil vi gjennomføre handlingene til ViewController
klasse. Men først bør vi instansere Mp3 spiller
forekomst. Oppdater implementeringen av viewDidLoad
metode som vist nedenfor.
overstyr func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player ()
playSong (_: AnyObject)
Skriv inn følgende i playSong (_: AnyObject)
metode.
@IBAction func playSong (sender: AnyObject) mp3Player? .Play ()
I denne metoden bruker vi spille
metode på mp3 spiller
gjenstand. Vi er på et punkt der vi kan begynne å teste appen nå. Kjør appen og trykk på avspillingsknappen. Sangen skal begynne å spille.
stopSong (_: AnyObject)
De stopSong (_: AnyObject)
Metode påberoper stoppmetoden på mp3 spiller
gjenstand.
@IBAction func stopSong (avsender: AnyObject) mp3Player? .Stop ()
Kjør appen igjen og trykk på avspillingsknappen. Du bør nå kunne stoppe sangen ved å trykke på stoppknappen.
pauseSong (_: AnyObject)
Som du kanskje har gjettet, pauseSong (_: AnyObject)
metode påberoper seg pause
metode på mp3 spiller
gjenstand.
@IBAction func pauseSong (sender: AnyObject) mp3Player? .Pause ()
playNextSong (_: AnyObject)
IBAction func playNextSong (sender: AnyObject) mp3Player? .NextSong (false)
I playNextSong (_: AnyObject)
, vi påberoper nextSong
metode på mp3 spiller
gjenstand. Legg merke til at vi passerer falsk
som en parameter, fordi sangen ikke fullførte å spille alene. Vi starter manuelt den neste sangen ved å trykke på neste knapp.
forrigeSong (_: AnyObject)
@IBAction func playPreviousSong (avsender: AnyObject) mp3Player? .RevligSong ()
Som du kan se, implementeringen av forrigeSong (_: AnyObject)
Metoden ligner veldig på nextSong (_: AnyObject)
. Alle knappene på MP3-spilleren skal fungere nå. Hvis du ikke har testet appen ennå, ville det være en god tid å sørge for at alt fungerer som forventet.
setVolume (_: UISlider)
De setVolume (_: UISlider)
metode påberoper seg setVolume
metode på mp3 spiller
gjenstand. Volumegenskapen er av typen Flyte
. Verdien varierer fra 0.0 til 1.0. De UISlider
objektet er satt opp med 0.0 som minimumsverdi og 1.0 som sin maksimale verdi.
@IBAction func setVolume (sender: UISlider) mp3Player? .SetVolume (sender.value)
Kjør appen en gang til og spill med volumreglaget for å teste at alt fungerer som det skal.
startTimer
De startTimer
metode instantiates en ny NSTimer
forekomst.
func startTimer () timer = NSTimer.scheduledTimerWithTimeInterval (1.0, mål: selvvalg: Selector ("updateViewsWithTimer:"), brukerInfo: null, gjentakelser: sant)
De scheduledTimerWithTimeInterval (_: mål: Velger: Userinfo: gjentagelser :)
initialiserer tar som parametre antall sekunder mellom avfyring av timeren, objektet som det skal kalles en metode på angitt av velger
, Metoden som blir kalt når timeren brenner, en valgfri brukerinformasjon
ordboken, og om timeren gjentas eller ikke, før den blir ugyldiggjort.
Vi bruker en metode som heter updateViewsWithTimer (_: NSTimer)
Som selector, så vil vi skape det neste.
updateViewsWithTimer (_: NSTimer)
De updateViewsWithTimer (_: NSTimer)
metode kalles updateViews
metode som vi vil implementere i neste trinn.
func updateViewsWithTimer (theTimer: NSTimer) updateViews ()
updateViews
De updateViews
Metoden oppdaterer Tracktime
og ProgressBar
visninger.
func updateViews () trackTime.text = mp3Player? .getCurrentTimeAsString () hvis la fremgang = mp3Player? .getProgress () progressBar.progress = fremgang
De tekst
tilhører Tracktime
er oppdatert med nåværende tid
eiendom, formatert som en streng ved å påkalle getCurrentTimeAsString
metode. Vi erklærer en konstant framgang
bruker mp3 spiller
's getProgress
metode og sett progressBar.progress
bruker den konstanten.
Nå må vi ringe startTimer
metode på de riktige stedene. Vi må starte timeren i playSong (_: AnyObject)
metode, den playNextSong (_: AnyObject)
metode, og playPreviousSong (_: AnyObject)
metode.
@IBAction func playSong (avsender: AnyObject) mp3Player? .Play () startTimer ()
@IBAction func playNextSong (sender: AnyObject) mp3Player? .NextSong (false) startTimer ()
@IBAction func playPreviousSong (avsender: AnyObject) mp3Player? .PreviousSong () startTimer ()
Vi må også stoppe tidsur
når du trykker på pause og stoppknappene. Du kan stoppe tidsur
objekt ved å påkalle ugyldig
metode på NSTimer
forekomst.
@IBAction func stopSong (sender: AnyObject) mp3Player? .Stop () updateViews () timer? .Validere ()
@IBAction func pauseSong (sender: AnyObject) mp3Player? .Pause () timer? .Validere ()
setTrackName
De setTrackName
Metoden setter tekst
tilhører trackName
ved å påkalle getCurrentTrackName
på mp3 spiller
gjenstand.
func setTrackName () trackName.text = mp3Player? .getCurrentTrackName ()
setupNotificationCenter
Når en sang avsluttes, skal den automatisk vise den neste sangens navn og begynne å spille den sangen. Også, når brukeren trykker på spill, neste eller tidligere knapper, setTrackName
Metoden bør påberopes. Det ideelle stedet å gjøre dette er queueTrack
metode av Mp3 spiller
klasse.
Vi trenger en måte å ha på Mp3 spiller
klassen forteller ViewController
klasse for å påkalle setTrackName
metode. For å gjøre det, bruker vi NSNotificationCenter
klasse. Meldingssentralen gir en måte å kringkaste informasjon gjennom et program. Ved å registrere som observatør med varslingssenteret, kan en gjenstand motta disse sendingene og utføre en operasjon. En annen måte å utføre denne oppgaven på er å bruke delegasjonsmønsteret.
Legg til følgende metode for ViewController
klasse.
func setupNotificationCenter () NSNotificationCenter.defaultCenter (). addObserver (selv, selector: "setTrackName", navn: "SetTrackNameText", objekt: null)
Vi får først en referanse til standardvarslingssenteret. Vi anvender deretter addObserver (_: selector: navn: objekt :)
metode på varslingssenteret. Denne metoden godtar fire parametere:
selv-
i dette tilfelletVed å passere inn nil
Som det siste argumentet lytter vi etter hvert varsel som har et navn på SetTrackNameText.
Nå må vi ringe denne metoden i visningskontrolløren viewDidLoad
metode.
overstyr func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter ()
For å legge inn varselet, påberoper vi oss postNotificationName (_: objekt :)
metode på standardvarslingssenteret. Som jeg nevnte tidligere, vil vi gjøre dette i queueTrack
metode av Mp3 spiller
klasse. Åpen MP3Player.swift og oppdatere queueTrack
metode som vist nedenfor.
func queueTrack () if (player! = nil) player = nil var feil: NSError? la url = NSURL.fileURLWithPath (spor [currentTrackIndex] som String) player = AVAudioPlayer (contentOfURL: url, feil: & feil) hvis la hasError = feil // SHOW ALERT ELLER ENKELT annet spiller? .delegate = selvspiller ?. prepareToPlay () NSNotificationCenter.defaultCenter (). postNotificationName ("SetTrackNameText", objekt: null)
Hvis du tester appen nå og lar en sang spilles helt gjennom, bør den begynne å spille neste sang automatisk. Men du lurer kanskje på hvorfor sangens navn ikke kommer opp under den første sangen. De i det
metode av Mp3 spiller
klassen ringer på queueTrack
metode, men siden den ikke har fullført initialiseringen, har den ingen innvirkning.
Alt vi trenger å gjøre er å ringe manuelt setTrackName
metode etter at vi har initialisert mp3 spiller
gjenstand. Legg til følgende kode i viewDidLoad
metode i ViewController.swift.
overstyr func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter () setTrackName () updateViews ()
Du vil merke at jeg også ringte updateViews
metode. På denne måten viser spilleren en tid på 00:00 i begynnelsen. Hvis du tester appen nå, bør du ha en fullt fungerende MP3-spiller.
Dette var en ganske lang opplæring, men du har nå en funksjonell MP3-spiller for å bygge og utvide på. Et forslag er å la brukeren velge en sang som skal spilles ved å implementere en UITableView
under spilleren. Takk for at du leser, og jeg håper du har lært noe nyttig.