Build en MP3-spiller med AV Foundation
60
Del
19
Del
Dette Cyber mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Hva du skal lage
AV Foundation er et rammeverk for å arbeide med lyd og visuelle medier på iOS og OSX. Bruke AV Foundation, kan du spille, fangst, og kode media. Det er ganske omfattende rammeverk og for hensikten med denne opplæringen vi vil fokusere på lyddelen. Konkret vil vi bruke AVAudioPlayer klasse å spille MP3-filer.
Start Prosjekt
Jeg har gitt en startpakke prosjekt som har alle de handlinger og utsalgssteder allerede er konfigurert, og med egnede metoder stumpet. Klassene prosjektet bruker, er allerede stumpet også slik at vi kan hoppe rett inn i koden. Du kan laste ned starter prosjektet fra GitHub.
1. Knytte AV Foundation Work
Før du kan bruke AV Foundation, må du knytte prosjektet mot rammen. I prosjekt Navigator, kontrollere at prosjektet er valgt. Under kategorien Generelt, gå til Koblede Rammer og biblioteker, og derfra kan velge AVFoundation.framework.
2. Filereader Class
I start prosjektet, vil du finne en fil som heter FileReader.swift. Åpne denne filen for å vise innholdet
importere UIKitclass Filereader. NSObject {}
Dette er en enkel spire av den klassen som vi skal bruke til å lese filer fra disk. Det arver fra NSObject. Vi skal implementere en fremgangsmåte, readFiles, noe som vil være en type metode. Type metoder tillate deg å kalle en metode på klassen selv, typen, i motsetning til en forekomst av klassen. Nedenfor er gjennomføringen av readFiles metoden
klasse funk readFiles () - >.; [String] {return NSBundle.mainBundle () pathsForResourcesOfType ("mp3", inDirectory: null). As! [String]}
Hoved bunt inneholder koden og ressurser for prosjektet, og det er her vi finner de MP3. Vi bruker metoden pathsForResourcesOfType (_: inDirectory :) metoden, som returnerer en matrise som inneholder banenavn for den angitte ressurstypen. I dette tilfellet er vi søker etter type "mp3". Fordi vi er ikke interessert i en bestemt katalog, passerer vi i null.
Denne klassen vil bli brukt av MP3Player klassen, som vi vil jobbe med neste.
3. MP3Player Class
Deretter åpner MP3Player.swift og vise innholdet
import UIKitimport AVFoundationclass MP3Player. NSObject, AVAudioPlayerDelegate {}
Legg merke til at vi tar i bruk den AVAudioPlayerDelegate protokollen. Denne protokollen erklærer en rekke nyttige metoder, hvorav den ene er audioPlayerDidFinishPlaying (_: hell :). Ved å implementere audioPlayerDidFinishPlaying (_: hell :) metode, vi vil bli varslet når lyden er ferdigspilt
Trinn 1:.. Egenskaper
Legg til følgende MP3Player.swift Anmeldelser
klasse MP3Player: NSObject, AVAudioPlayerDelegate {var spiller: AVAudioPlayer? Var currentTrackIndex = 0 Var spor: [String] = [String] ()}
Spilleren eiendommen vil være en forekomst av AVAudioPlayer klassen, som vi vil bruke til å spille, pause og stoppe MP3. Den currentTrackIndex variable holder oversikt over hvilke MP3 spilles i øyeblikket. Til slutt vil sporene variabelen være en rekke banene til listen over MP3-filer som er inkludert i programmets bunt
Trinn 2:. Init
overstyring init () {spor = FileReader.readFiles () super.init () queueTrack ();}
Under initialisering påberope vi Filereader er readFiles metode for å hente banene til MP3-filer og lagre denne listen i spor array. Fordi dette er et utpekt initializer, må vi kaller init metoden i superklassen. Til slutt, vi kaller queueTrack, som vi skal skrive neste
Trinn 3:. QueueTrack
Legg til følgende gjennomføring for queueTrack metoden til MP3Player klassen
func queueTrack. () {if {spiller = null} Var feil (spiller = null!): NSError? la url = NSURL.fileURLWithPath (spor [currentTrackIndex] som String) spiller = AVAudioPlayer (contentsOfURL: url, error: & feil) hvis la hasError = error {//SHOW ALERT eller noe} else {spiller .delegate = selv spiller? ? .prepareToPlay ()}}
Fordi vi vil bli Instantiating en ny AVAudioPlayer eksempel hver gang denne metoden kalles, gjør vi en liten rengjøring ved å sette spilleren til null.
Vi erklærer en valgfri NSError og en konstant url. Vi påberope fileURLWithPath (_ :) hente banen til dagens MP3 og lagre verdien i url. Vi passerer den låter matrise som et parameter ved hjelp currentTrackIndex som senket. Husk spor matrisen inneholder banene til MP3-filer, ikke en referanse til MP3-filer selv.
på å bruke spilleren, passerer vi url konstant og feiling variabel inn i AVAudioPlayer sin initializer. Hvis initialisering skjer å mislykkes, skyldes feil variabel befolket med en beskrivelse av feilen.
Hvis vi ikke støter på en feil, setter vi spillerens delegat til selv og påkalle prepareToPlay metoden på spilleren. Den prepareToPlay metode preloads bufferne og overtar audio hardware, noe som minimerer eventuelle etterslep når du ringer stykket metoden
Trinn 4:. Leke
spill metoden sjekker først for å se om ikke lyden er allerede spiller ved å sjekke det treffende navnet spiller eiendom. Hvis lyden ikke spiller, påkaller det stykket metode for spilleren eiendommen
func play () {if .playing spiller == false {spiller Beskytt din Nintendo DS ()}
Trinn 5.?: stoppe
Holdeplassen Metoden sjekker først om lyden spilleren er allerede spiller. Hvis det er, påkaller det stopp metoden og setter currentTime eiendommen til 0. Når du aktiverer stopp metoden, det bare stopper lyden. Det tilbakestiller ikke lyden tilbake til begynnelsen, og det er derfor vi trenger å gjøre det manuelt.
Func stop () {if spiller? .playing == True {spilleren? .stop () Spiller? .currentTime = 0 }}
Trinn 6: pause
Akkurat som stopp-metoden, må vi først se etter om lyden spiller spiller. Hvis det er, påberope vi pause metoden
func pause () {if spiller .playing == true {spiller .pause ()}?}
Trinn 7:. NextSong
nextSong (_: Bool) metode køer opp neste sang, og hvis spilleren spiller, spiller den sangen. Vi ønsker ikke den neste sangen spilles om spilleren er satt på pause. Imidlertid er denne metoden også kalles når en sang er ferdig spilt. I så fall trenger vi ønsker å spille neste sang, som er hva parameter songFinishedPlaying er for
func nextSong (songFinishedPlaying: Bool).? {Var playerWasPlaying = false hvis spilleren .playing == true {spiller ? .stop () playerWasPlaying = true} currentTrackIndex ++ hvis currentTrackIndex > = tracks.count {currentTrackIndex = 0} queueTrack () hvis playerWasPlaying || songFinishedPlaying {spilleren? Beskytt din Nintendo DS ()}}
playerWasPlaying variabelen brukes til å fortelle hvorvidt spilleren spilte da denne metoden ble startet. Om sangen ble spilt, påberope vi stopp metoden på spilleren og satt playerWasPlaying til sann.
Deretter øke vi currentTrackIndex og sjekke for å se om den er større enn eller lik tracks.count. Tellingen tilhører en matrise gir oss totalt antall elementer i tabellen. Vi må være sikker på at vi ikke prøve å få tilgang til et element som ikke finnes i sporene array. For å unngå dette, setter vi currentTrackIndex tilbake til det første elementet i matrisen dersom det er tilfelle.
Til slutt påberope vi queueTrack å få den neste sangen klar og spille den sangen om enten playerWasPlaying eller songFinishedPlaying er sant.
Trinn 8: previousSong
previousSong metoden fungerer veldig lik nextSong. Den eneste forskjellen er at vi minske currentTrackIndex og sjekk om det er lik 0. Hvis det er, setter vi det til i indeksen for den siste elementet i gruppen.
Func previousSong () {var playerWasPlaying = false hvis spilleren ? .playing == true {spiller .stop () playerWasPlaying = sant?} currentTrackIndex-- hvis currentTrackIndex < 0 {currentTrackIndex = tracks.count - 1} queueTrack () hvis playerWasPlaying {? Spiller Beskytt din Nintendo DS ()}}
Ved å benytte både nextSong og previousSong metoder, er vi i stand til å bla gjennom alle MP3-filer og starte på nytt når vi kommer til begynnelsen eller slutten av listen
Trinn 9:.. getCurrentTrackName
getCurrentTrackName metoden blir navnet på MP3 uten skjøte
func getCurrentTrackName () - > String {la trackName = spor [currentTrackIndex] .lastPathComponent.stringByDeletingPathExtension tilbake trackName}
Vi får en referanse til hva dagens MP3 er ved hjelp av spor [currentTrackIndex]. Husk imidlertid at disse er banene til MP3-filer og ikke selve filene selv. Banene er ganske lang, fordi det er den fullstendige banen til MP3-filer.
På min maskin, for eksempel, er lik den første elementet i spor utvalg "/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 vil 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å MP3 seg selv. Den NSString klassen definerer to egenskaper som kan hjelpe oss. Som navnet tilsier, den lastPathComponent eiendommen returnerer den siste komponenten i en bane. Som du kanskje har gjettet, stringByDeletingPathExtension eiendommen fjerner forlengelse.
Trinn 10:. getCurrentTimeAsString
getCurrentTimeAsString metoden bruker currentTime eiendom spilleren forekomst og returnerer det som en lesbar streng (f.eks 01:02)
func getCurrentTimeAsString () - > String {var ? sekunder = 0 Var minutter = 0 hvis .currentTime la tiden = spiller {sekunder = Int (tid)% 60 minutter = (Int (tid) /60)% 60} returnere String (format: "% 0.2d:% 0.2d ", minutter, sekunder)}
currentTime Eiendommen er av typen NSTimeInterval, som ligger bare en typealias for en dobbel. Vi bruker litt matematikk for å få sekunder og minutter, slik at vi konvertere tid til en Int siden vi trenger å arbeide med hele tall. Hvis du ikke er kjent med resten operatør (%), finner den resten etter delingen av ett nummer av en annen. Hvis tidsvariabelen var lik 65, så sekunder ville være lik 5, fordi vi bruker 60.
Trinn 11: getProgress
getProgress metode brukes av UIProgressView omgang å gi en indikasjon på hvor mye av MP3 har spilt. Fremgangen er representert med en verdi fra 0.0 til 1.0 som en Float
func getProgress () - >.? Float {var theCurrentTime = 0.0 Var theCurrentDuration = 0,0 hvis la currentTime = spiller .currentTime, varighet = spiller .duration {theCurrentTime = currentTime theCurrentDuration = varighet} retur Float (theCurrentTime /theCurrentDuration)}
For å få denne verdien, deler vi spillerens currentTime eiendom av spilleren varighet eiendom, vi lagre disse verdiene i variablene theCurrentTime og theCurrentDuration. Som currentTime, er av typen NSTimeInterval varigheten eiendommen og det representerer varigheten av sangen i sekunder
Trinn 12:. SetVolume
setVolume (_: Float) metode påkaller setVolume metoden spilleren eksempel
func setVolume. (volum: Float) {spiller .volume = volum?}
Trinn 13: audioPlayerDidFinishPlaying (_: hell :)
audioPlayerDidFinishPlaying (_: hell :) metode er en fremgangsmåte av den AVAudioPlayerDelegate protokollen. Denne metoden tar som parameter den AVAudioPlayer forekomst og en boolsk. Den boolsk er satt til true hvis lydspiller er ferdigspilt gjeldende sang
func audioPlayerDidFinishPlaying. (Spiller: AVAudioPlayer, hell flagg: Bool) {if flagg == true {nextSong (true)}}
Hvis Sangen hell ferdig med å spille, vi kaller nextSong metoden, som går i oppfyllelse siden sangen ferdig med å spille på egen hånd.
Dette fullfører MP3Player klassen. Vi vil se det litt senere, etter implementering av handlingene til ViewController klassen.
4. ViewController Class
Åpne ViewController.swift og vise innholdet
mport UIKitimport AVFoundationclass ViewController. UIViewController {var mp3-spiller: MP3Player? Var timer: NSTimer? IBOutlet Svak Var trackName: UILabel! IBOutlet Svak Var Tracktime: UILabel! IBOutlet Svak Var progressbar: UIProgressView! styre func viewDidLoad () {super.viewDidLoad ()}IBAction func playSong (avsender: AnyObject) {}IBAction func stopSong (avsender: AnyObject) {}IBAction func pauseSong (avsender: AnyObject) {}IBAction func playNextSong ( avsender: AnyObject) {}IBAction func setVolume (avsender: UISlider) {}IBAction func playPreviousSong (avsender: AnyObject) {} overstyring func didReceiveMemoryWarning () {super.didReceiveMemoryWarning () //Kast noen ressurser som kan gjenskapes. }}
MP3Player variabelen er en forekomst av MP3Player klassen vi gjennomført tidligere. Timeren variable vil bli brukt til å oppdatere Tracktime og progressbar visninger hver andre.
I de neste trinnene, vil vi gjennomføre handlingene til ViewController klassen. Men først skal vi instantiate MP3Player eksempel. . Oppdatere gjennomføringen av viewDidLoad metoden som vist nedenfor
styre func viewDidLoad () {super.viewDidLoad () MP3Player = MP3Player ()}
Trinn 1: playSong (_: AnyObject)
Enter følgende i playSong (_: AnyObject) metode
IBAction func playSong. (avsender: AnyObject) {? MP3Player Beskytt din Nintendo DS ()}
I denne metoden, påberope vi stykket metoden på mp3-spiller objektet. Vi er på et punkt der vi kan begynne å teste appen nå. Kjør programmet og trykker på play-knappen. Sangen skal begynne å spille
Trinn 2:. StopSong (_: AnyObject)
stopSong (_: AnyObject). Metoden påkaller stopp metoden på mp3-spiller objektet
IBAction func stopSong (avsender: AnyObject) {? MP3Player .stop ()}
Kjør app igjen og trykke på avspillingsknappen. Du skal nå være i stand til å stoppe sangen ved å trykke på stoppknappen
Trinn 3:. PauseSong (_: AnyObject)
Som du kanskje har gjettet, pauseSong (_: AnyObject) metode påkaller pause metoden på mp3-spiller objektet
IBAction func pauseSong. (avsender: AnyObject) {MP3Player .pause ()?}
Trinn 4: playNextSong (_: AnyObject)
IBAction func playNextSong (avsender: {? MP3Player .nextSong (falsk)} AnyObject)
I playNextSong (_: AnyObject), påberope vi nextSong metoden på mp3-spiller objektet. Vær oppmerksom på at vi passerer falsk som en parameter, fordi sangen ikke er ferdigspilt på egen hånd. Vi er manuelt starter neste sang ved å trykke på neste-knappen
Trinn 5:. PreviousSong (_: AnyObject)
IBAction func playPreviousSong (avsender: AnyObject) {? MP3Player .previousSong ()}
Som du kan se, gjennomføringen av previousSong (_: AnyObject) metoden er svært lik som nextSong (_: AnyObject). Alle knappene på MP3-spilleren skal være funksjonelle nå. Hvis du ikke har testet appen ennå, nå ville være et godt tidspunkt å sørge for at alt fungerer som forventet
Trinn 6:. SetVolume (_: UISlider)
setVolume (_ : UISlider) -metoden påkaller setVolume metoden på mp3-spiller objektet. Volumet Eiendommen er av typen Float. Verdien varierer fra 0.0 til 1.0. Den UISlider objektet er satt opp med 0,0 som sin minimumsverdi og 1,0 som sin høyeste verdi
IBAction func setVolume (avsender: UISlider). {? MP3Player .setVolume (sender.value)}
Kjør app én mer tid og leke med volumknappen for å teste at alt fungerer som det skal
Trinn 7:.. startTimer
startTimer metoden instantiates en ny NSTimer eksempel
func startTimer () {timer = NSTimer.scheduledTimerWithTimeInterval (1,0, target: selvtillit, Velger: Selector ("updateViewsWithTimer:"), Userinfo: null, gjentar: true)}
scheduledTimerWithTimeInterval (_: target: Velger: Userinfo: gjentar :) initializer tar som parametere antall sekunder mellom avfyring av timeren, til objektet som kaller en metode på spesifisert av velgeren, metoden som blir kalt når tidtakeren branner, en valgfri Userinfo ordboken, og hvorvidt tidtakeren gjentas til den er ugyldig.
Vi bruker en metode som heter updateViewsWithTimer. (_: NSTimer) som velgeren, så vi vil lage den neste
Trinn 8: updateViewsWithTimer (_: NSTimer)
Den updateViewsWithTimer (_: NSTimer) metoden kaller updateViews metoden, som vi vil gjennomføre i neste trinn
func updateViewsWithTimer (theTimer: NSTimer). {updateViews ()}
Trinn 9: updateViews
Den updateViews metoden oppdaterer Tracktime og progressbar visninger.
func updateViews () {trackTime.text = mp3-spiller? .getCurrentTimeAsString () hvis la fremgang = mp3-spiller? .getProgress () {progressBar.progress = fremgang}} < p> Teksten eiendom Tracktime er oppdatert med den currentTime eiendom, formatert som en streng ved å påberope seg getCurrentTimeAsString metoden. Vi erklærer en konstant fremgang ved å bruke mp3-spiller er getProgress metode, og satt progressBar.progress bruke det konstant
Trinn 10:. Kabling Up Timer
Nå må vi kalle startTimer metode på de riktige stedene. Vi må starte tidtakeren i playSong (_: AnyObject) metoden, playNextSong (_: AnyObject) -metoden, og playPreviousSong (_: AnyObject) metode
IBAction func playSong. (Avsender: AnyObject) {mp3-spiller? Beskytt din Nintendo DS () startTimer ()}IBAction func playNextSong (avsender: AnyObject) {.nextSong mp3-spiller (falsk) startTimer ()} @ IBAction func playPreviousSong (avsender: AnyObject)? {MP3Player .previousSong () startTimer ()} < h3> Trinn 11: Stoppe Timer
Vi trenger også å stoppe timeren når pause og stoppe knappene trykkes. Du kan stoppe tidtakeren objekt ved å påberope seg ugyldig metoden på NSTimer eksempel
IBAction func stopSong. (Avsender: AnyObject) {? MP3Player .stop () updateViews () timer .invalidate ()} @ IBAction func pauseSong (avsender: AnyObject) {? MP3Player .pause () timer .invalidate ()}
Trinn 12: setTrackName
setTrackName metoden angir tekst eiendom trackName ved å påberope getCurrentTrackName på mp3-spiller objektet .
func setTrackName () {trackName.text = MP3Player .getCurrentTrackName ()?}
Trinn 13: setupNotificationCenter
Når en sang er ferdig som spiller, det skal automatisk vise neste sang navn og begynne å spille den sangen. Også når brukeren trykker på play, neste, eller tidligere knappene, setTrackName metoden bør gjøres gjeldende. Det ideelle stedet å gjøre dette på er den queueTrack metoden i MP3Player klassen.
Vi trenger en måte å ha den MP3Player klassen fortelle ViewController klassen påberope setTrackName metoden. For å gjøre det, vil vi bruke NSNotificationCenter klassen. Varslingssenteret tilbyr en måte å kringkaste informasjon gjennom et program. Ved å registrere deg som observatør med varslingssenteret, kan et objekt motta disse sendingene og utføre en operasjon. En annen måte å utføre denne oppgaven vil være å bruke delegasjonen mønster.
Legg følgende metode til ViewController klassen.
Func setupNotificationCenter () {NSNotificationCenter.defaultCenter (). AddObserver (selv, Velger: "setTrackName", navn: "SetTrackNameText", objekt: null)}
Vi først få en henvisning til standard varslingssenteret. Vi deretter påberope seg addObserver (_: velgeren: navn: objekt :) metoden på varslingssenteret. Denne metoden tar fire parametere:
objektet registrere seg som observatør, selv i dette tilfellet
meldingen som vil bli sendt til observatøren da er postet meldingen
< li> navnet på varslingen for å registrere observatøren
det objektet som varsler observatøren ønsker å motta
Ved bestått i null som siste argument, vi lytter for hver varsling som har et navn på SetTrackNameText.
Nå må vi kalle denne metoden i visningen kontrollerens viewDidLoad metode.
styre func viewDidLoad () {super.viewDidLoad () MP3Player = MP3Player () setupNotificationCenter () }
Trinn 14: Publisering varslings
For å sende meldingen, påberope vi postNotificationName (_: objekt :) metoden på standard varslingssenteret. Som jeg nevnte tidligere, vil vi gjøre dette i queueTrack metoden i MP3Player klassen. Åpne MP3Player.swift og oppdatere queueTrack metoden som vist nedenfor
func queueTrack () {if {spiller = null} Var feil. (Spiller = null!): NSError? la url = NSURL.fileURLWithPath (spor [currentTrackIndex] som String) spiller = AVAudioPlayer (contentsOfURL: url, error: & feil) hvis la hasError = error {//SHOW ALERT eller noe} else {spiller .delegate = selv spiller? ? .prepareToPlay () NSNotificationCenter.defaultCenter () postNotificationName ("SetTrackNameText", objekt: null).}}
Hvis du tester app nå og la en sang spille hele veien gjennom, det skal begynne å spille neste sang automatisk . Men du lurer kanskje på hvorfor sangens navn ikke dukker opp i løpet av den første sangen. Init metoden i MP3Player klassen kaller queueTrack metoden, men siden det ikke er ferdig med oppstarten, har det ingen innvirkning.
Alt vi trenger å gjøre er å manuelt ringe setTrackName metoden etter at vi initialisere mp3-spiller objektet.
Overstyring func viewDidLoad () {super.viewDidLoad () MP3Player = MP3Player () setupNotificationCenter () setTrackName () updateViews ()} Legg til følgende kode i viewDidLoad metoden i ViewController.swift.
Du ll merke til at jeg også kalt updateViews metoden. På denne måten viser det spiller en tid på 00:00 ved start. Hvis du tester app nå, bør du ha en fullt fungerende MP3-spiller.
Konklusjon
Dette var en ganske lang tutorial, men du har nå en funksjonell MP3-spiller for å bygge og utvide. Et forslag er å tillate brukeren å velge en sang til å spille ved å implementere en UITableView under spilleren. Takk for lesing, og jeg håper du har lært noe nyttig.