Welkom bij de zevende aflevering van onze serie over het ontwerpen en bouwen van een versie uit de jaren tachtig van de iOS? -Telefoon? app. In deze zelfstudie laat ik zien hoe u de juiste audiotoon afspeelt voor elk nummer op het toetsenblok van de telefoon.
Dit is een momentopname van wat we in de loop van deze serie gaan bouwen:
Dit is een meerdelige serie ontworpen om tussentijdse iOS SDK-onderwerpen te leren. De inhoud wordt steeds complexer naarmate de reeks vordert. Als je je op een gegeven moment verloren voelt in het volgen van deze serie, moet je misschien een stapje terug doen en je een weg banen door onze Learn Objective-C-serie of onze Begins iOS SDK Development-serie.
In de laatste zelfstudie in deze serie heb ik laten zien hoe ik een iPhone-oproep kan initiëren nadat ik een nummer op het toetsenbord heb gekozen en ook hoe ik de nummerweergave moet formatteren wanneer een gebruiker op een cijfer tikt. In deze zelfstudie voegen we de beloofde aanrakingstonen toe aan elk van de 0 - 9 knoppen.
De iOS SDK wordt geleverd met meerdere frameworks die verschillende methoden bieden voor het afspelen van geluidsfragmenten en zelfs het genereren van audio on-the-fly. Appels Programmagids voor multimedia beschrijft het doel van elk beschikbaar audioframework als volgt:
Een hele reeks tutorials zou kunnen worden gewijd aan elk van de frameworks in de bovenstaande lijst, maar het volstaat om te zeggen dat we voor het doel van deze tutorial het Audio Toolbox-framework zullen gebruiken vanwege één uniek aanbod: System Sound Services. Systeemgeluidsservices zijn een interface op C-niveau die is bedoeld voor het afspelen van korte geluidseffecten van de gebruikersinterface en andere kleine audiofragmenten van 30 seconden of korter.
Het proces voor het afspelen van een audioclip met System Sound Services omvat drie stappen:
De rest van deze tutorial zal dit proces implementeren om vooraf opgenomen DTMF-tonen te spelen voor de cijfers 0-9 van het bediendeel.
Waarom gebruiken we vooraf opgenomen tonen in plaats van het genereren van de juiste frequentie on-the-fly? In essentie om tijd te besparen en om deze tutorial toegankelijker te houden door de wiskunde te vermijden die te maken heeft met sinusoïdale functies en het genereren van frequenties. Als u in plaats daarvan naar die route wilt gaan, vindt u waarschijnlijk de volgende artikelen handig:
Wil je echt weten hoe je on-the-fly geluid kunt genereren? Als dit bericht ten minste 10 reacties ontvangt waarin een zelfstudie wordt gevraagd over hoe je vanaf 1 mei 2011 de audio helemaal opnieuw kunt maken, dan maak ik een geavanceerde iOS SDK-serie over dat onderwerp. Geen beloften dat het specifiek DTMF-aanraaktonen betreft, maar het zal zeker iets geweldigs zijn.
Laten we, met de theoretische kennis uit de weg, een duik nemen in de code en deze functie laten uitvoeren!
We moeten beginnen met het importeren van het Audio Toolbox-framework in onze applicatie om de System Sound Services beschikbaar te maken voor onze code. Selecteer hiervoor het project "PhoneAppSkin" in het deelvenster Projectnavigator in Xcode, selecteer vervolgens "PhoneAppSkin" onder "TARGETS" en selecteer tenslotte het tabblad "Fasen opbouwen". Na dit te hebben gedaan, zou uw scherm er ongeveer zo uit moeten zien:
Klik vervolgens op de vervolgkeuzelijst "Binaire elementen koppelen met bibliotheken" en klik op het symbool "+" om een nieuw kader toe te voegen aan de koppelingsfase van ons project..
Zoek ten slotte het kader "AudioToolbox" in het pop-upvenster en klik vervolgens op "Toevoegen".
Open vervolgens de PhoneViewController.h bestand en voeg de regel toe die nodig is om het Audio Toolbox-framework daadwerkelijk in uw klas te importeren:
#importeren#importeren
De Audio Toolbox-functies moeten nu toegankelijk zijn voor uw klas!
Download en open de broncode die bij dit Mobiletuts + bericht hoort en zoek de map met de titel "Audio". Sleep deze hele map naar de map "Bronnen" van de Xcode Project Navigator en zorg ervoor dat u de optie "Kopiëren" aanvinkt wanneer hierom wordt gevraagd. Je zou moeten eindigen met een scherm dat ongeveer zo is:
In PhoneViewController.h, voeg de volgende C-stijl array-declaratie toe:
@interface PhoneViewController: UIViewController SystemSoundID toneSSID's [10];
Lijn 13 verklaart een C-type array van type SystemSoundID
met een maximale capaciteit van 10.
Het opslaan van systeemgeluids-ID's in deze array zal ons in staat stellen snel naar de juiste geluidsfragment in de numberButtonPressed:
methode later.
Open PhoneViewController.m en spring naar de initWithCoder
methode op regel 17. Wanneer de PhoneViewController
wordt eerst geïnitialiseerd en de initWithCoder
methode wordt genoemd, willen we systeemgeluiden registreren voor elke toon die op het toetsenbord wordt gebruikt met de iOS-systeemgeluidsserver. Nadat een geluidsclip is geregistreerd bij de geluidsserver, kunnen we de server opdracht geven om het geluidsbestand later af te spelen wanneer op het toetsenblok wordt gedrukt.
Voer de volgende code in om de 0-9-aanrakingstonen te registreren:
-(id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; if (self) phoneNumberString = [[NSString alloc] init]; voor (int count = 0; count < 10; count++) NSString *toneFilename = [NSString stringWithFormat:@"DTMF_%02d", count]; NSURL *toneURLRef = [[NSBundle mainBundle] URLForResource:toneFilename withExtension:@"wav"]; SystemSoundID toneSSID = 0; AudioServicesCreateSystemSoundID( (CFURLRef) toneURLRef, &toneSSID ); toneSSIDs[count] = toneSSID; return self;
Op regel 24, een voor
lus die 10 keer wordt herhaald begint. Het doel van dit voor
Loop is om een nieuw systeemgeluids-ID toe te voegen aan de toneSSIDs
matrix voor elk van de aanraaktoetsen behorend bij de toetsen 0 - 9.
Op regel 25, een instantie van NSString
wordt geïnstantieerd die de bestandsnaam van de relevante DTMF-aanraaktoon zal bevatten. Een interessante opmerking over deze regel is de stringWithFormat:
method call en de % 02d
formaat specificatie. Deze indelingsspecificator zet elk cijfer om in een nulgevuld cijfer van 2 tekens. Dus, bijvoorbeeld 0 wordt '00', 1 wordt '01', 2 wordt '02', enz.
Op regel 27, de NSBundle
class wordt gebruikt om een bestandssysteempad te genereren naar de bestandsnaam gegenereerd op regel 25 met een extensie van "wav" toegevoegd. NSLog
deze waarde als u het volledige pad voor uzelf wilt zien.
Lijn 29 creëert een variabele om de te houden SystemSoundID
die vervolgens door de geluidsserver van het iOS-systeem wordt gegenereerd.
Als een kanttekening,
SystemSoundID
is slechts een typedefinitie voor het Mac-typeUInt32
, wat zelf een typefout isniet lang ondertekend
. Daarom hadden we de variabele op deze regel van het type kunnen declarerenniet lang ondertekend
, maar dit zou een slechte praktijk zijn, omdat toekomstige iOS-releases deSystemSoundID
type, waardoor de code breekt. Desalniettemin is het goed om dit in gedachten te houden bij het werken metSystemSoundID
s omdat de compiler soms waarschuwt voor incompatibelniet lang ondertekend
types.
Lijnen 31 - 34 zijn een c-stijl functie aanroepen AudioServicesCreateSystemSoundID
, wat een CFURL
(Core Foundation-URL) van het audiobestandpad om een systeemgeluids-id voor en een SystemSoundID-verwijzing te genereren die wordt gebruikt om de SSID op te slaan nadat deze is gemaakt. Merk op hoe het ampersand-teken (dat wil zeggen '&') vóór de. Verschijnt toneSSID
variabele op regel 33? Dit is een unaire prefix-operator die de. Converteert toneSSID
parameter in het geheugenadres van de variabele in plaats van de waarde die in het geheugen voor die variabele is opgeslagen. Dit wordt gedaan zodat de AudioServicesCreateSystemSoundID
functie kan het gegenereerde SSID nummer direct opslaan in de toneSSID
geheugenadres, waardoor de functie-aanroeper (dat wil zeggen onze methode) toegang heeft tot de gegenereerde SSID zonder de SSID daadwerkelijk terug te geven van de functie.
Klinkt een beetje verwarrend? Waarschijnlijk zal het tenzij je al ervaring hebt met programmeren in een taal als C, C ++ of Go. Omdat Objective-C een strikte superset is van de C-taal, is de iOS-SDK soms afhankelijk van bibliotheken die zijn geschreven in procedurele C. Als de C-syntaxis niet logisch voor u is, hoeft u zich daar nu niet al te veel zorgen over te maken, maar neem het als een uitdaging om in de toekomst je SDK-kennis van iOS aan te vullen met de basisprincipes van de C-taal!
Op regel 35, de index van de toneSSIDs
c-stijl array aangewezen door de stroom tellen
waarde wordt de waarde toegewezen die door de AudioServicesCreateSystemSoundID
functie. Naar deze SSID-waarde wordt later verwezen om de juiste toon af te spelen wanneer de gebruiker op de cijfers van het toetsenbord tikt.
De numberButtonPressed:
methode wordt elke keer dat de touchUpInside
evenement vuurt voor knoppen 0 - 9. Omdat indices 0-9 van de toneSSIDs
array bevat nu de bijbehorende toon voor elke knop, de volgende drie regels code zijn voldoende om de juiste toon te spelen:
-(IBAction) numberButtonPressed: (UIButton *) pressedButton int toneIndex = [pressedButton.titleLabel.text intValue]; SystemSoundID toneSSID = toneSSIDs [toneIndex]; AudioServicesPlaySystemSound (toneSSID); self.phoneNumberString = [self.phoneNumberString stringByAppendingString: pressedButton.titleLabel.text]; [self display Phone Nummer];
Regel 96 converteert de tekstwaarde van de ingedrukte UIButton
titel van een geheel getal uit een string.
Met het cijfer voor het toetsenblok verkregen, regel 97 haalt een SystemSoundID
van de toneSSIDs
rangschikking.
Op regel 98, de AudioServicesPlaySystemSound
De functie wordt aangeroepen met de SSID die zojuist is opgehaald om het afspelen van de toetstoon te starten.
Dat is het! Ga je gang en opslaan en bouwen het project nu, en je zou moeten merken dat de cijfers van het toetsenbord geluidseffecten hebben!
Er is een klein probleem met de huidige oplossing. Merk je de vertraging op tussen het aanraken van de knop en de gegenereerde toon? In deel 6 van deze serie zijn de knoppen op het toetsenbord ingesteld om de touchUpInside
actie. Deze actie wordt geactiveerd nadat de gebruiker zijn vinger van de knop haalt. De toon moet echter worden afgespeeld zodra de gebruiker op de knop tikt, niet na het verwijderen van de vinger. Om dit op te lossen, open PhoneView.xib
, Verwijder de touchUpInside
IBAction
referenties voor alle knoppen, en vervolgens elke knop te binden touchdown
actie voor de numberButtonPressed:
methode.
Als u hulp nodig hebt bij het uitzoeken hoe u deze stap moet uitvoeren, raadpleegt u gewoon deel 6, stap 1 in deze serie.
Deze zelfstudie is een wervelende tournee geweest door het kader van Audio Toolbox en System Sound Services. Als u vragen heeft, kunt u deze achterlaten in de opmerkingen hieronder en ik zal mijn best doen om te reageren. Natuurlijk zijn er niet genoeg uren op de dag om alle oude berichten elke dag opnieuw te bekijken op nieuwe reacties, dus als de maanden aanhouden, heb je misschien meer geluk door contact met me op te nemen via Twitter: @markhammonds.