Välkommen till den sjunde avbetalningen i vår serie om hur man både designar och bygger en 1980-version av IOS? Telefonen? app. I denna handledning demonstrerar jag hur du spelar en lämplig ljudton för varje nummer på telefonens knappsats.
Detta är en snapshot av vad vi kommer att bygga under denna serie:
Detta är en serie med flera delar som är utformad för att lära ut mellanliggande iOS SDK-ämnen. Innehållet blir alltmer komplicerat när serien går vidare. Om du vid någon tidpunkt hittar dig förlorad i att följa den här serien kan du behöva ta ett steg tillbaka och arbeta dig igenom vår Learn Objective-C-serie eller vår början iOS SDK Development-serie.
I den sista handledningen i denna serie visade jag hur man faktiskt skulle initiera ett iPhone-samtal efter att ha ringt ett nummer på knappsatsen och också hur man formaterar numrervisningen när en användare kränger en siffra. I den här handledningen lägger vi till de utlovade touchtonerna till var och en av knapparna 0-9.
IOS SDK levereras med flera ramar som tillhandahåller olika metoder för att spela ljudklipp och till och med generera ljud på flykt. Apples Multimedia Programmeringsguide beskriver syftet med varje tillgänglig ljudram enligt följande:
En hel serie av handledningar kan vara tillägnad varje ram i ovanstående lista, men tillräckligt för att säga att för denna handledning ska vi använda Audio Toolbox-ramen på grund av ett unikt erbjudande: Systemljudtjänster. Systemljudtjänster är ett C-nivågränssnitt som är avsett för att spela korta användargränssnittsljud och andra små ljudklipp med 30 sekunder eller mindre.
Processen för att spela ett ljudklipp med System Sound Services omfattar tre steg:
Resten av denna handledning kommer att implementera denna process för att spela inspelade DTMF-toner för knappsatsen siffror 0-9.
Varför använder vi förinspelade toner istället för att generera lämplig frekvens på flyget? I huvudsak för att spara tid och för att hålla denna handledning mer tillgänglig genom att undvika matematik som är involverad i sinusformiga funktioner och frekvensgenerering. Om du vill gå den vägen istället hittar du troligtvis följande artiklar:
Vill du verkligen veta hur man genererar ljud på flyget? Om det här inlägget får minst 10 kommentarer som begär en handledning om hur man skapar ljud från början den 1 maj 2011 ska jag göra en avancerad iOS SDK-serie om det här ämnet. Inga löften att det kommer att innebära DTMF-toner specifikt, men det kommer definitivt att bli något häftigt.
Med den teoretiska kunskapen ur vägen, låt oss dyka in i koden och få den här funktionen klar!
Vi måste börja med att importera Audio Toolbox-ramverket till vår applikation för att göra Systemljudtjänsten tillgänglig för vår kod. För att göra det, välj "PhoneAppSkin" -projektet i rutan Projekt Navigator i Xcode, välj sedan "PhoneAppSkin" under "TARGETS" och välj slutligen fliken "Byggfaser". Därefter ska din skärm se ut så här:
Därefter, klicka på länken "Länka binära med bibliotek" och klicka på "+" -symbolen för att lägga till en ny ram för projektets länkfas.
Slutligen hitta "AudioToolbox" -ramen i popup-fönstret och klicka sedan på "Lägg till".
Öppna sedan upp PhoneViewController.h fil och lägg till den rad som behövs för att faktiskt importera Audio Toolbox-ramverket till din klass:
#importera#importera
Funktionerna för ljudverktygslådan ska nu vara tillgängliga för din klass!
Hämta och öppna källkoden som bifogas denna Mobiletuts + post och hitta mappen med titeln "Audio". Dra hela den här mappen till mappen "Resurser" i Xcode Project Navigator, se till att du väljer "Kopiera" när du blir ombedd. Du borde sluta med en skärm så här:
I PhoneViewController.h, lägg till följande C-format array deklaration:
@interface PhoneViewController: UIViewController SystemSoundID toneSSIDs [10];
Linje 13 förklarar en typ av C-typ av typ SystemSoundID
med en maximal kapacitet på 10.
Lagring av systemljud-ID i denna array gör det möjligt för oss att snabbt hänvisa till lämpligt ljudklipp i numberButtonPressed:
metod senare.
Öppna PhoneViewController.m och hoppa till initWithCoder
metod på linje 17. När PhoneViewController
initialiseras först och initWithCoder
Metoden heter, vi vill registrera systemljud för varje ton som ska användas på knappsatsen med iOS-systemljudservern. När ett ljudklipp är registrerat hos ljudservern kan vi instruera servern att spela upp ljudfilen senare när knappsatsen trycks ned.
För att registrera knapparna 0-9, lägg till följande kod:
-(id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; om (själv) phoneNumberString = [[NSString alloc] init]; för (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;
På rad 24, en för
loop som kommer att iterera 10 gånger börjar. Syftet med detta för
loop är att lägga till ett nytt systemljud ID till toneSSIDs
array för var och en av de beräkningstoner som är associerade med tangenterna 0-9.
På linje 25, en förekomst av NSString
är instansierad som håller filnamnet för den relevanta DTMF-tonen. En intressant anteckning på denna rad är stringWithFormat:
metodsamtal och % 02d
format specifier. Detta format specifier omvandlar alla siffror till en nollpolstret siffra med 2 tecken i längd. Så blir till exempel 0 '00', blir 1 '01', 2 blir '02', etc.
På linje 27, de NSBundle
klassen används för att generera en filsystemväg till filnamnet som genereras på rad 25 med en förlängning av "wav" bifogad. NSLog
Detta värde om du vill se hela sökvägen för dig själv.
Linje 29 skapar en variabel för att hålla SystemSoundID
som kommer att genereras av iOS-systemljudservern nästa.
Som en sidnot,
SystemSoundID
är bara en typedef för Mac Typeuint32
, vilket är själv en typedef förunsigned long
. Följaktligen kunde vi ha förklarat variabeln på denna typ av typunsigned long
, men det skulle vara dålig övning eftersom framtida iOS-utgåvor kan ändraSystemSoundID
skriv, vilket orsakar att koden bryts. Det är dock bra att komma ihåg detta när du arbetar medSystemSoundID
s eftersom kompilatorn ibland kommer att varna om inkompatiblaunsigned long
typer.
Linjer 31 - 34 är ett c-stilfunktionssamtal till AudioServicesCreateSystemSoundID
, som tar a CFURL
(Core Foundation URL) för ljudfilbanan för att skapa ett Systemljud ID för och en SystemSoundID-referens som används för att lagra SSID-filen efter att den har skapats. Lägg märke till hur ampersandkaraktären (dvs '&') visas före toneSSID
variabel på rad 33? Detta är ett unary prefix operatör som konverterar toneSSID
parametern i variabelns minnesadress istället för det värde som lagras i minnet för den variabeln. Detta är gjort så att AudioServicesCreateSystemSoundID
funktionen kan lagra det genererade SSID numret direkt i toneSSID
minnesadressen, så att funktionsanroparen (dvs. vår metod) åtkomst till det genererade SSID utan att egentligen överföra SSID tillbaka från funktionen.
Låter lite förvirrande? Det kommer förmodligen inte om du redan har erfarenhet av programmering på ett språk som C, C ++ eller Go. Eftersom Objective-C är en strikt superset av C-språket, är iOS SDK ibland beroende av bibliotek som är skrivna i procedur C. Om C-syntaxen inte är meningsfull för dig, oroa dig inte för det för mycket just nu, men ta det som en utmaning att komplettera din iOS SDK-kunskap med grunden för C-språket i framtiden!
På ledning 35, indexet för toneSSIDs
c-stil array betecknad av strömmen räkna
värdet tilldelas det värde som skapas av AudioServicesCreateSystemSoundID
fungera. Detta SSID-värde kommer att refereras senare för att spela rätt ton när användaren tappar på knappsatsens nummer.
De numberButtonPressed:
Metoden heter varje gång touchUpInside
händelse bränder för knapparna 0 - 9. Eftersom index 0-9 av toneSSIDs
array innehåller nu den motsvarande tonen för varje knapp, är följande tre streckkod tillräckligt för att spela den lämpliga tonen:
-(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 displayPhoneNumber];
Linje 96 konverterar textvärdet av den pressade UIButton
titel till ett heltal från en sträng.
Med den uppringda siffran som erhållits, rad 97 hämtar a SystemSoundID
från toneSSIDs
array.
På rad 98, de AudioServicesPlaySystemSound
funktionen heter med SSID bara hämtad för att starta uppspelning av beredningstangenten.
Det är allt! Gå vidare och spara och bygga projektet nu, och du bör upptäcka att knappsatsen har ljudeffekter!
Det finns ett litet problem med den nuvarande lösningen. Märker du förseningen mellan att trycka på knappen och den genererade tonen? I del 6 i denna serie var knappsatsens knappar inställda för att utlösa touchUpInside
verkan. Den här åtgärden brinner när användaren tar bort fingret från knappen. Tonen ska dock spelas så fort användaren knackar på knappen, inte efter att ha tagit bort fingret. För att åtgärda detta, öppna PhoneView.xib
, ta bort touchUpInside
IBAction
referenser för alla knappar och bind sedan varje knapps landning
åtgärd till numberButtonPressed:
metod.
Om du behöver hjälp att ta reda på hur du gör det här steget, hänvisar du bara till del 6, steg 1 i den här serien.
Denna handledning har varit en virvelvindsturnering i Audio Toolbox Framework och System Sound Services. Om du har frågor, var god att lämna dem i kommentarerna nedan och jag gör mitt bästa för att svara. Självklart finns det inte tillräckligt med timmar på dagen för mig att kolla alla mina tidigare inlägg för nya kommentarer varje dag, så som månaderna bär på dig kan ha bättre lycka kontakta mig via Twitter: @markhammonds.