Voorbeeld-app: zo laat je je iPhone praten

In de app die we in dit artikel bouwen, laten we de iPhone (of de Simulator) getallen uitspreken. Dat doen we op de volgende manier:

  • We gebruiken geen Storyboard: alles gebeurt in programmacode.
  • Onze app heeft Auto Layout. De constraints voegen we dus ook in programmacode toe.
  • We gebruiken de NumberFormatter-class om getallen om te zetten in tekst.
  • We gebruiken de AVSpeechSynthesizer-class om onze iPhone te kunnen laten praten.

De complete programmacode vind je hieronder. Maak in Xcode een Single View App (FileNewProject):

Xcode: kies een template

Geef je app een naam, bijvoorbeeld SpraakDemo. Open vervolgens het ViewController.swift-bestand en vervang de inhoud ervan door de code die je onderaan dit artikel vindt. Start je app, beweeg de slider en druk op de Spreek uit-button.

App-voorbeeld

De belangrijkste onderdelen in onze app

Als je, terwijl je de inhoud van ViewController.swift bewerkt, op ⌃6 (‘Control 6’) drukt, zie je het document-menu:

Document-menu van Xcode

In dit menu zie je een overzicht van alle properties en methodes in ViewController.swift.

Tip: gebruik // MARK
Door in je code // MARK te gebruiken met daarachter een korte beschrijving, kun je ‘kopjes’ maken die in het document-menu worden getoond.

De gebruikersinterface: slider, button, label en Auto Layout

Omdat we het Storyboard niet gebruiken, voegen we onze drie views toe in programmacode. Ook met de Auto Layout-constraints doen we dat.

De slider: .maakSlider()

Nadat we een slider met UISlider() ‘uit de fabriek’ hebben gehaald, wijzigen we de properties voor de minimale en maximale waarde.

Tip: gebruik underscores voor grote getallen
Door underscores te gebruiken, kun je getallen die je aan een Int-variabele toewijst, leesbaarder maken: 100_000_000_000 is duidelijker dan 100000000000

Daarna voegen we de slider toe aan de hoofd-view en tot slot ‘hangen we er een actie’ aan: zodra de gebruiker de slider heeft verplaatst en de waarde van de slider dus is veranderd, wordt de methode .bewaarWaarde(sender:) aangeroepen. Als we het Storyboard zouden hebben gebruikt, hadden we hiervoor een @IBAction gemaakt.

De button: .maakButton()

We halen een nieuwe button op met UIButton(). Daarna stellen we de titel in. Vergeet daarbij de kleur niet op te geven, met de .setTitleColor(_:for:)-methode.

Ook bij de button hoort een actie: zodra de gebruiker de button aanraakt, wordt de methode .spreekWaardeUit()-aangeroepen.

Het label: maakLabel()

We hebben een label nodig om het getal in te kunnen zetten. De inhoud van dat label kan behoorlijk groot worden, vandaar dat we een label maken dat meer dan één regel kan hebben. Ook stellen we in dat woorden die niet meer op een regel passen, in hun geheel naar de volgende regel moeten.

Auto Layout: maakAutoLayoutConstraints()

Als je wel eens met Auto Layout in het Storyboard hebt gewerkt, weet je dat je voortdurend bezig bent om constraints aan views toe te voegen. Dit kan ook in programmacode; immers, een constraint is een object (NSLayoutConstraint).

In ons voorbeeld maken we elke constraint met een heel uitgebreide initializer:

NSLayoutConstraint(item:attribute:relatedBy:toItem:attribute:multiplier:constant:)

Tip: Views en Auto Layout
Als je wel wat hulp bij Auto Layout kunt gebruiken, is het eBook Apps bouwen met Swift – Views en Auto Layout misschien iets voor je: klik hier voor meer informatie.

Nadat we een serie constraints hebben gemaakt, voegen we ze toe aan de (super)view waar ze bijhoren:

Tot slot zorgen we ervoor dat UIKit de view waarvoor we zelf de Auto Layout hebben gemaakt, verder met rust laat:

De NumberFormatter-class

Om een getal ‘netjes’ te kunnen tonen, kun je de NumberFormatter-class gebruiken. Deze class kan van getallen String-waarden maken en houdt daarbij rekening met de manier waarop getallen in een land of taal worden getoond.

In onze app gebruiken we de NumberFormatter-class twee keer: we zetten ‘puntjes’ tussen de duizendtallen en we zetten een getal om in letterlijke tekst.

De belangrijkste properties van een NumberFormatter zijn:

  • De .locale: een struct die informatie bevat over het land en de taal waarvoor het getal moet worden ‘opgemaakt’.
  • De .numberStyle: een enum die aangeeft hoe het getal moet worden opgemaakt.

Nadat een NumberFormatter weet welke locale en welke numberStyle hij moet gebruiken, kan hij elk getal omzetten in een String.

De spraaksynthesizer: AVSpeechSynthesizer

Om tekst door je iPhone te laten uitspreken, gebruik je de AVSpeechSynthesizer-class. Deze class is onderdeel van het AVFoundation-framework.

In principe gebruik je een AVSpeechSynthesizer als volgt:

  1. Je maakt een voice: een ‘stem’, in de gewenste taal.
  2. Je maakt een utterance (de beste vertaling ervoor is ‘uiting’): de tekst die je wilt laten uitspreken en de stem waarmee je dat wilt doen. De uiting wordt bewaard als AVSpeechUtterance-object.
  3. Je vertelt de AVSpeechSynthesizer dat hij de uiting moet uitspreken.

Omdat we de stem telkens nodig hebben, maken we die maar één keer. Daarna bewaren we hem in een property, stem. Alleen als het lukt om een stem te maken (als er een stem beschikbaar is in de taal die de gebruiker op zijn iPhone heeft ingesteld), maken we een AVSpeechSynthesizer. Dit alles gebeurt in één methode:

De tekst uitspreken

Nadat we een stem en spraaksynthesizer hebben, kunnen we de iPhone onze waarde laten uitspreken. We kijken of er een stem is, maken vervolgens de uiting (een AVSpeechUtterance) en zetten de spraaksynthesizer aan het werk.

De complete programmacode

Vervang de inhoud van ViewController.swift door onderstaande programmacode. Meer hoef je niet te doen: er is geen Storyboard er zijn verder geen classes nodig. Succes!

Zelf apps leren maken

Wil je leren hoe je apps maakt voor je iPhone of iPad? Wellicht is het eBook iOS Apps bouwen met Swift – Programmeren met Swift iets voor je: ruim 400 pagina’s met alles wat je moet weten om zelf apps te kunnen bouwen – ook als je nog nooit eerder hebt geprogrammeerd.

Klik hier voor meer informatie over het eBook iOS Apps bouwen met Swift – Programmeren met Swift.

  • Erwin

    Leuke app, bedankt Roelf. Ik merk wel op dat ik een flinke lap tekst krijg in xcode waarmee ik geen raad weet. Zie onderstaande:

    2017-02-26 00:07:54.598883 TalkingApp[8239:354038] 0x60800034cd90 Copy matching assets reply: XPC_TYPE_DICTIONARY { count = 2, transaction: 0, voucher = 0x0, contents =

    “Assets” => : { length = 1261 bytes, contents = 0x62706c6973743030d4010203040506666758247665727369… }

    “Result” => : 0

    }

    2017-02-26 00:07:54.602327 TalkingApp[8239:354038] 0x600000155df0 Copy assets attributes reply: XPC_TYPE_DICTIONARY { count = 1, transaction: 0, voucher = 0x0, contents =

    “Result” => : 1

    }

    2017-02-26 00:07:54.603017 TalkingApp[8239:354038] [MobileAssetError:1] Unable to copy asset attributes

    2017-02-26 00:07:54.603452 TalkingApp[8239:354038] Could not get attribute ‘LocalURL’: Error Domain=MobileAssetError Code=1 “Unable to copy asset attributes” UserInfo={NSDescription=Unable to copy asset attributes}

    Iemand enig idee wat ik hiermee moet?
    Groeten,
    Erwin

    • Erwin, die rommel kun je negeren. Xcode is sinds versie 8 wat luidruchtiger geworden, helaas…

      • Erwin

        Hoi Roelf,
        Bedankt voor het snelle antwoord 🙂