AV Foundation is een raamwerk voor het werken met audio- en visuele media op iOS en OSX. Met AV Foundation kunt u media afspelen, vastleggen en coderen. Het is een vrij uitgebreid kader en voor het doel van deze tutorial zullen we ons concentreren op het audiogedeelte. Concreet zullen we de AVAudioPlayer
klasse om MP3-bestanden af te spelen.
Ik heb een startersproject geleverd waarbij alle acties en stopcontacten al zijn geconfigureerd en de juiste methoden zijn uitgewerkt. De klassen die het project gebruikt, zijn ook al uitgedost, zodat we direct in de code kunnen duiken. Je kunt het startersproject downloaden van GitHub.
Voordat u AV Foundation kunt gebruiken, moet u het project koppelen aan het framework. In de Project Navigator, zorg ervoor dat uw project is geselecteerd. Onder de Algemeen tab, ga naar Gekoppelde kaders en bibliotheken en van daaruit kies je AVFoundation.framework.
FileReader
KlasseIn het startersproject vindt u een bestand met de naam FileReader.swift. Open dit bestand om de inhoud te bekijken.
import UIKit-klasse FileReader: NSObject
Dit is een eenvoudig gedeelte van de klas dat we zullen gebruiken om bestanden van schijf te lezen. Het erft van NSObject
. We zullen een methode implementeren, readFiles
, welke een typemethode zal zijn. Met typen kunt u een methode in de klasse zelf aanroepen, het type, in tegenstelling tot een instantie van de klasse. Hieronder is de implementatie van de readFiles
methode.
class func readFiles () -> [String] retourneer NSBundle.mainBundle (). pathsForResourceOfType ("mp3", inDirectory: nihil) als! [Draad]
De hoofdbundel bevat de code en bronnen voor uw project en hier zullen we de MP3's vinden. We gebruiken de methode pathsForResourcesOfType (_: inDirectory :)
methode, die een array retourneert met de padnamen voor het opgegeven resourcetype. In dit geval zoeken we naar type "Mp3"
. Omdat we niet geïnteresseerd zijn in een specifieke directory, komen we binnen nul
.
Deze klasse wordt gebruikt door de MP3 speler
klas, waar we volgende aan zullen werken.
MP3 speler
KlasseOpen vervolgens MP3Player.swift en bekijk de inhoud ervan.
importeer UIKit import AVFoundation class MP3Player: NSObject, AVAudioPlayerDelegate
Merk op dat we de AVAudioPlayerDelegate
protocol. Dit protocol declareert een aantal bruikbare methoden, waarvan er één is audioPlayerDidFinishPlaying (_: met succes :)
. Door de audioPlayerDidFinishPlaying (_: met succes :)
methode, ontvangen we een melding wanneer het afspelen is voltooid.
Voeg het volgende toe aan MP3Player.swift.
class MP3Player: NSObject, AVAudioPlayerDelegate var player: AVAudioPlayer? var currentTrackIndex = 0 var-tracks: [String] = [String] ()
De speler
eigenschap wordt een instantie van de AVAudioPlayer
klasse, die we zullen gebruiken om de MP3's af te spelen, te pauzeren en te stoppen. De currentTrackIndex
variabele houdt bij welke MP3 momenteel wordt afgespeeld. eindelijk, de sporen
variabele is een array van paden naar de lijst met MP3's die zijn opgenomen in de bundel van de toepassing.
in het
override init () tracks = FileReader.readFiles () super.init () queueTrack ();
Tijdens de initialisatie roepen we de FileReader
's readFiles
methode om de paden van de MP3's op te halen en deze lijst op te slaan in de sporen
matrix. Omdat dit een aangewezen initialisator is, moeten we de in het
methode van de superklasse. Eindelijk bellen we queueTrack
, die we hierna zullen schrijven.
queueTrack
Voeg de volgende implementatie toe voor de queueTrack
methode om de MP3 speler
klasse.
func queueTrack () if (player! = nil) player = nil var error: NSError? laat url = NSURL.fileURLWithPath (tracks [currentTrackIndex] als tekenreeks) player = AVAudioPlayer (contentsOfURL: url, error: & error) if let hasError = error // LAAT ALERT OF IETS else player? .delegate = self player ?. prepareToPlay ()
Omdat we een nieuw maken AVAudioPlayer
elke keer dat deze methode wordt aangeroepen, doen we een beetje huishoudelijk door te stellen speler
naar nul
.
We verklaren een optioneel NSError
en een constante url
. We roepen fileURLWithPath (_ :)
om het pad naar de huidige MP3 op te halen en de waarde op te slaan url
. We passeren de sporen
array als een parameter met currentTrackIndex
als het subscript. Vergeet niet dat de array tracks de paden naar de MP3's bevat, en niet een verwijzing naar de MP3-bestanden zelf.
Om de speler
, we passeren de url
constant en fout
verander in de AVAudioPlayer
's initializer. Als de initialisatie toevallig mislukt, de fout
variabele wordt gevuld met een beschrijving van de fout.
Als we geen fout tegenkomen, stellen we de gedelegeerde van de speler in zelf
en roep de prepareToPlay
methode op de speler. De prepareToPlay
methode vooraf laadt de buffers en verwerft de audio-hardware, die elke vertraging minimaliseert bij het aanroepen van de spelen
methode.
spelen
De spelen
methode controleert eerst of het geluid al speelt of niet, door de toepasselijke naam te controleren spelen
eigendom. Als het geluid niet wordt afgespeeld, roept het de spelen
methode van de speler
eigendom.
func play () if player? .playing == false player? .play ()
hou op
De hou op
methode controleert eerst of de audiospeler al aan het spelen is. Als dat zo is, roept het de hou op
methode en stelt de huidige tijd
eigendom aan 0. Wanneer u de hou op
methode, het stopt gewoon de audio. Het zet de audio niet terug naar het begin, daarom moeten we dit handmatig doen.
func stop () if player? .playing == true player? .stop () player? .currentTime = 0
pauze
Net als de hou op
methode, controleren we eerst of de audiospeler speelt. Als dat zo is, roepen we het pauze
methode.
func pause () if player? .playing == true player? .pause ()
volgende liedje
De nextSong (_: Bool)
methode maakt een wachtrij voor het volgende nummer en, als de speler speelt, wordt dat nummer afgespeeld. We willen niet dat het volgende nummer wordt afgespeeld als de speler is onderbroken. Deze methode wordt echter ook aangeroepen wanneer een nummer wordt afgespeeld. In dat geval willen we het volgende nummer spelen, wat de parameter is songFinishedPlaying
is voor.
func nextSong (songFinishedPlaying: Bool) var playerWasPlaying = false if player? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex ++ if currentTrackIndex> = tracks.count currentTrackIndex = 0 queueTrack () als playerWasPlaying | | songFinishedPlaying player? .play ()
De playerWasPlaying
variabele wordt gebruikt om aan te geven of de speler aan het spelen was toen deze methode werd aangeroepen. Als het nummer werd afgespeeld, roepen we het hou op
methode op de speler
En instellen playerWasPlaying
naar waar
.
Vervolgens verhogen we de currentTrackIndex
en controleer om te zien of het groter dan of gelijk aan is tracks.count
. De tellen
eigenschap van een array geeft ons het totale aantal items in de array. We moeten zeker weten dat we niet proberen toegang te krijgen tot een element dat niet bestaat in de sporen
matrix. Om dit te voorkomen, hebben we ingesteld currentTrackIndex
terug naar het eerste element van de array als dat het geval is.
Ten slotte roepen we aan queueTrack
om het volgende nummer klaar te maken en dat nummer af te spelen als een van beide playerWasPlaying
of songFinishedPlaying
is waar
.
previousSong
De previousSong
methode werkt erg op volgende liedje
. Het enige verschil is dat we het currentTrackIndex
en controleer of het gelijk is aan 0. Als dat zo is, stellen we het in op de index van het laatste element in de array.
func previousSong () var playerWasPlaying = false if player? .playing == true player? .stop () playerWasPlaying = true currentTrackIndex-- if currentTrackIndex < 0 currentTrackIndex = tracks.count - 1 queueTrack() if playerWasPlaying player?.play()
Door beide te gebruiken volgende liedje
en previousSong
methodes, kunnen we alle MP3's doorlopen en opnieuw beginnen wanneer we het begin of het einde van de lijst bereiken.
getCurrentTrackName
De getCurrentTrackName
methode krijgt de naam van de MP3 zonder de extensie.
func getCurrentTrackName () -> String let trackName = tracks [currentTrackIndex] .lastPathComponent.stringByDeletingPathExtension return trackName
We krijgen een verwijzing naar wat de huidige MP3 is door te gebruiken titels [currentTrackIndex]
. Onthoud echter dat dit de paden naar de MP3's zijn en niet de eigenlijke bestanden zelf. De paden zijn vrij lang, omdat het het volledige pad naar de MP3-bestanden is.
Op mijn computer, bijvoorbeeld, het eerste element van de sporen
array is gelijk aan "/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"Dit pad zou natuurlijk anders zijn op een echt apparaat.
We hebben een grote reeks die het pad naar de MP3 bevat, maar we willen gewoon de naam van de MP3 zelf. De NSString
klasse definieert twee eigenschappen die ons kunnen helpen. Zoals de naam al aangeeft, de lastPathComponent
eigenschap retourneert het laatste onderdeel van een pad. Zoals je misschien al geraden had, de stringByDeletingPathExtension
eigenschap verwijdert de extensie.
getCurrentTimeAsString
De getCurrentTimeAsString
methode gebruikt de huidige tijd
eigendom van de speler
instantie en retourneert het als een voor mensen leesbare string (bijv., 01:02).
func getCurrentTimeAsString () -> String var seconds = 0 var minutes = 0 if let time = player? .currentTime seconds = Int (time)% 60 minutes = (Int (time) / 60)% 60 return String (format : "% 0.2d:% 0.2d", minuten, seconden)
De huidige tijd
eigendom is van het type NSTimeInterval
, dat is gewoon een typealias
voor een Dubbele
. We gebruiken wat wiskunde om de seconden
en notulen
, ervoor zorgen dat we converteren tijd
aan een Int
omdat we met hele getallen moeten werken. Als u niet bekend bent met de restoperator (%), vindt deze de rest na deling van het ene getal door het andere. Als het tijd
variabele was gelijk aan 65, dan seconden
zou gelijk zijn aan 5 omdat we gebruiken 60.
getProgress
De getProgress
methode wordt gebruikt door de UIProgressView
bijvoorbeeld om een indicatie te geven van hoeveel van de MP3 heeft gespeeld. Deze voortgang wordt weergegeven door een waarde van 0.0 naar 1.0 als een Vlotter
.
func getProgress () -> Float var theCurrentTime = 0.0 var theCurrentDuration = 0.0 als currentTime = player? .currentTime, duration = player? .duration theCurrentTime = currentTime theCurrentDuration = duration return Float (theCurrentTime / theCurrentDuration)
Om deze waarde te krijgen, verdelen we de speler
's huidige tijd
eigendom door de speler
's looptijd
property, slaan we deze waarden op in de variabelen theCurrentTime
en theCurrentDuration
. Net zoals huidige tijd
, de looptijd
eigendom is van het type NSTimeInterval
en het vertegenwoordigt de duur van het nummer in seconden.
setVolume
De setVolume (_: Float)
methode roept de setVolume
methode van de speler
aanleg.
func setVolume (volume: Float) speler?. volume = volume
audioPlayerDidFinishPlaying (_: met succes :)
De audioPlayerDidFinishPlaying (_: met succes :)
methode is een methode van de AVAudioPlayerDelegate
protocol. Deze methode neemt als parameters de AVAudioPlayer
instance en een boolean. De boolean is ingesteld op waar
als de audiospeler het huidige nummer heeft afgespeeld.
func audioPlayerDidFinishPlaying (speler: AVAudioPlayer, succesvol vlag: Bool) if flag == true nextSong (true)
Als het nummer met succes is afgespeeld, noemen we het volgende liedje
methode, binnenkomen waar
sinds het liedje op zichzelf is gespeeld.
Hiermee is het MP3 speler
klasse. We zullen het later nog een keer bekijken, na het implementeren van de acties van de ViewController
klasse.
ViewController
KlasseOpen ViewController.swift en bekijk de inhoud ervan.
mport UIKit import AVFoundation class ViewController: UIViewController var mp3Player: MP3Player? var timer: NSTimer? @IBOutlet zwakke var trackName: UILabel! @IBOutlet zwakke var trackTime: UILabel! @IBOutlet zwakke var-voortgangBar: UIProgressView! override func viewDidLoad () super.viewDidLoad () @IBAction func playSong (afzender: AnyObject) @IBAction func stopSong (afzender: AnyObject) @IBAction func pauseSong (afzender: AnyObject) @IBAction func playNextSong ( afzender: AnyObject) @IBAction func setVolume (afzender: UISlider) @IBAction func playPreviousSong (afzender: AnyObject) override func didRiveMemoryWarning () super.didReceiveMemoryWarning () // Beschik alle bronnen die opnieuw kunnen worden gemaakt.
De MP3 speler
variabele is een instantie van de MP3 speler
klasse die we eerder hebben geïmplementeerd. De timer
variabele zal worden gebruikt om de tracktime
en voortgangsbalk
bekeken elke seconde.
In de volgende paar stappen zullen we de acties van de ViewController
klasse. Maar eerst moeten we de MP3 speler
aanleg. Update de implementatie van de viewDidLoad
methode zoals hieronder getoond.
override func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player ()
playSong (_: AnyObject)
Voer het volgende in de playSong (_: AnyObject)
methode.
@IBAction func playSong (afzender: AnyObject) mp3Player? .Play ()
In deze methode roepen we de spelen
methode op de MP3 speler
voorwerp. We zijn nu zover dat we de app nu kunnen gaan testen. Start de app en druk op de afspeelknop. Het nummer zou moeten beginnen te spelen.
stopSong (_: AnyObject)
De stopSong (_: AnyObject)
methode roept de stop methode op de MP3 speler
voorwerp.
@IBAction func stopSong (afzender: AnyObject) mp3Player? .Stop ()
Start de app opnieuw en tik op de afspeelknop. Je zou nu het nummer kunnen stoppen door op de stopknop te tikken.
pauseSong (_: AnyObject)
Zoals je misschien al geraden had, de pauseSong (_: AnyObject)
methode roept de pauze
methode op de MP3 speler
voorwerp.
@IBAction func pauseSong (afzender: AnyObject) mp3Player? .Pause ()
playNextSong (_: AnyObject)
IBAction func playNextSong (afzender: AnyObject) mp3Player? .NextSong (false)
In playNextSong (_: AnyObject)
, we roepen het volgende liedje
methode op de MP3 speler
voorwerp. Merk op dat we slagen vals
als een parameter, omdat het nummer niet zelfstandig is afgespeeld. We beginnen het volgende nummer handmatig door op de volgende knop te drukken.
previousSong (_: AnyObject)
@IBAction func playPreviousSong (afzender: AnyObject) mp3Player? .PreviousSong ()
Zoals u kunt zien, is de implementatie van de previousSong (_: AnyObject)
methode lijkt erg op die van nextSong (_: AnyObject)
. Alle knoppen van de MP3-speler moeten nu functioneel zijn. Als je de app nog niet hebt getest, zou het nu een goed moment zijn om te zorgen dat alles werkt zoals verwacht.
setVolume (_: UISlider)
De setVolume (_: UISlider)
methode roept de setVolume
methode op de MP3 speler
voorwerp. De volume-eigenschap is van het type Vlotter
. De waarde varieert van 0.0 naar 1.0. De UISlider
object is ingesteld met 0.0 als de minimumwaarde en 1.0 als maximale waarde.
@IBAction func setVolume (afzender: UISlider) mp3Player? .SetVolume (sender.value)
Start de app nog een keer en speel met de volumeregelaar om te testen of alles correct werkt.
startTimer
De startTimer
methode maakt een nieuw NSTimer
aanleg.
func startTimer () timer = NSTimer.scheduledTimerWithTimeInterval (1.0, target: self, selector: Selector ("updateViewsWithTimer:"), userInfo: nil, herhalingen: true)
De scheduledTimerWithTimeInterval (_: doel: selector: UserInfo: herhalingen :)
initializer neemt als parameters het aantal seconden tussen het afvuren van de timer, het object waaraan een methode moet worden aangeroepen, gespecificeerd met keuzeschakelaar
, de methode die wordt aangeroepen wanneer de timer start, een optionele gebruikers informatie
woordenboek en of de timer wordt herhaald of niet totdat deze ongeldig wordt.
We gebruiken een methode genaamd updateViewsWithTimer (_: NSTimer)
als de selector, dus we zullen het volgende creëren.
updateViewsWithTimer (_: NSTimer)
De updateViewsWithTimer (_: NSTimer)
methode noemt het updateViews
methode, die we in de volgende stap zullen implementeren.
func updateViewsWithTimer (theTimer: NSTimer) updateViews ()
updateViews
De updateViews
methode werkt het tracktime
en voortgangsbalk
keer bekeken.
func updateViews () trackTime.text = mp3Player? .getCurrentTimeAsString () if let progress = mp3Player? .getProgress () progressBar.progress = progress
De tekst
eigendom van tracktime
is bijgewerkt met de huidige tijd
eigenschap, opgemaakt als een tekenreeks door de getCurrentTimeAsString
methode. We verklaren een constante vooruitgang
de ... gebruiken MP3 speler
's getProgress
methode en stel in progressBar.progress
gebruik die constante.
Nu moeten we de startTimer
methode op de juiste plaatsen. We moeten de timer starten in de playSong (_: AnyObject)
methode, de playNextSong (_: AnyObject)
methode, en de playPreviousSong (_: AnyObject)
methode.
@IBAction func playSong (afzender: AnyObject) mp3Player? .Play () startTimer ()
@IBAction func playNextSong (afzender: AnyObject) mp3Player? .NextSong (false) startTimer ()
@IBAction func playPreviousSong (afzender: AnyObject) mp3Player? .PreviousSong () startTimer ()
We moeten ook stoppen met de timer
wanneer de pauze- en stopknoppen worden ingedrukt. Je kunt het stoppen timer
object door de ontzenuwen
methode op de NSTimer
aanleg.
@IBAction func stopSong (afzender: AnyObject) mp3Player? .Stop () updateViews () timer? .Invalidate ()
@IBAction func pauseSong (afzender: AnyObject) mp3Player? .Pause () timer? .Invalidate ()
setTrackName
De setTrackName
methode stelt de tekst
eigendom van trackname
door aan te roepen getCurrentTrackName
op de MP3 speler
voorwerp.
func setTrackName () trackName.text = mp3Player? .getCurrentTrackName ()
setupNotificationCenter
Als een nummer is afgelopen, wordt de naam van het volgende nummer automatisch weergegeven en wordt het nummer afgespeeld. Wanneer de gebruiker op de knoppen play, next of vorige drukt, wordt de setTrackName
methode moet worden aangeroepen. De ideale plek om dit te doen is het queueTrack
methode van de MP3 speler
klasse.
We hebben een manier nodig om de MP3 speler
klasse vertel het ViewController
klasse om het setTrackName
methode. Om dat te doen, zullen we de NSNotificationCenter
klasse. Het meldpunt biedt een manier om informatie door een programma heen uit te zenden. Door zich als waarnemer bij het meldpunt te registreren, kan een object deze uitzendingen ontvangen en een bewerking uitvoeren. Een andere manier om deze taak te volbrengen is om het delegatiepatroon te gebruiken.
Voeg de volgende methode toe aan de ViewController
klasse.
func setupNotificationCenter () NSNotificationCenter.defaultCenter (). addObserver (zelf, selector: "setTrackName", naam: "SetTrackNameText", object: nihil)
We krijgen eerst een verwijzing naar het standaard meldingscentrum. We roepen vervolgens de addObserver (_: selector: naam: object :)
methode op het meldingscentrum. Deze methode accepteert vier parameters:
zelf
in dit gevalDoor binnen te komen nul
als het laatste argument, luisteren we naar elke melding die een naam heeft SetTrackNameText.
Nu moeten we deze methode in de view-controller's noemen viewDidLoad
methode.
override func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter ()
Om de melding te plaatsen, roepen we de postNotificationName (_: object :)
methode op het standaard meldingscentrum. Zoals ik eerder al zei, zullen we dit doen in de queueTrack
methode van de MP3 speler
klasse. Open MP3Player.swift en werk het queueTrack
methode zoals hieronder getoond.
func queueTrack () if (player! = nil) player = nil var error: NSError? laat url = NSURL.fileURLWithPath (tracks [currentTrackIndex] als tekenreeks) player = AVAudioPlayer (contentsOfURL: url, error: & error) if let hasError = error // LAAT ALERT OF IETS else player? .delegate = self player ?. prepareToPlay () NSNotificationCenter.defaultCenter (). postNotificationName ("SetTrackNameText", object: nil)
Als je de app nu test en een nummer helemaal door laat spelen, zou het het volgende nummer automatisch moeten spelen. Maar je vraagt je misschien af waarom de naam van het nummer niet verschijnt tijdens het eerste nummer. De in het
methode van de MP3 speler
klasse noemt het queueTrack
methode, maar omdat het niet is voltooid, heeft het geen effect.
Het enige wat we moeten doen is handmatig de setTrackName
methode nadat we de MP3 speler
voorwerp. Voeg de volgende code toe aan de viewDidLoad
methode in ViewController.swift.
override func viewDidLoad () super.viewDidLoad () mp3Player = MP3Player () setupNotificationCenter () setTrackName () updateViews ()
Je zult merken dat ik ook de updateViews
methode. Op deze manier toont de speler een tijd van 00:00 aan het begin. Als je de app nu test, zou je een volledig functionele MP3-speler moeten hebben.
Dit was een vrij lange tutorial, maar je hebt nu een functionele MP3-speler om te bouwen en uit te breiden. Een suggestie is om de gebruiker toe te staan een nummer te kiezen om te spelen door een UITableView
onder de speler. Bedankt voor het lezen en ik hoop dat je iets nuttigs hebt geleerd.