iOS 8 een aangepast toetsenbord maken in Swift

Vanaf iOS 8 kunnen uw toepassingen aangepaste functionaliteit en inhoud uitbreiden buiten uw app, en deze beschikbaar maken voor gebruikers terwijl ze andere apps of het besturingssysteem gebruiken. Een manier om het besturingssysteem uit te breiden is door een aangepast toetsenbord te maken.

In deze zelfstudie laat ik je zien hoe je je eigen aangepaste toetsenbord kunt maken met behulp van Swift en de nieuwe app-uitbreidings-API's. Voordat we dat doen, gaan we bespreken wat een toetsenbordextensie kan doen, wat het niet kan doen en wat het moet doen om goedgekeurd te worden voor de App Store.

1. Overzicht

Een aangepast toetsenbord vervangt het systeemtoetsenbord voor gebruikers die mogelijkheden willen, zoals een nieuwe tekstinvoermethode of de mogelijkheid om tekst in te voeren in een taal die niet op andere wijze door het besturingssysteem wordt ondersteund.

De essentiële functie van een aangepast toetsenbord is eenvoudig, reageert op tikken, gebaren of andere invoergebeurtenissen en levert tekst in de vorm van een niet-toegeschreven NSString object op het tekstinvoegpunt van het huidige tekstinvoerobject.

Nadat een gebruiker een toetsenbord heeft gekozen, blijft het de standaardwaarde wanneer een app wordt geopend. Om deze reden het toetsenbord moet sta toe dat de gebruiker overschakelt naar een ander toetsenbord.

Er zijn twee essentiële ontwikkelaars voor elk aangepast toetsenbord:
Vertrouwen. Uw aangepaste toetsenbord geeft u toegang tot wat een gebruiker typt, dus vertrouwen tussen u en uw gebruiker is essentieel.
Een toets "volgend toetsenbord". De bekwaamheid waarmee een gebruiker naar een ander toetsenbord kan overschakelen, maakt deel uit van de gebruikersinterface van een toetsenbord; je moet er een opgeven op je toetsenbord. - App Extension Programming Guide

Als u slechts een paar knoppen aan het systeemtoetsenbord hoeft toe te voegen, moet u kijken naar aangepaste weergaven voor gegevensinvoer.

2. Vereisten en beperkingen

Wat een aangepast toetsenbord niet kan doen

Er zijn bepaalde tekstinvoerobjecten waarvoor uw aangepaste toetsenbord niet geschikt is om in te typen. Deze omvatten beveiligde tekstvelden voor het invoeren van wachtwoorden en telefoonpad-objecten, zoals de velden met telefoonnummers in de Contacten toepassing.

Uw aangepaste toetsenbord heeft geen toegang tot de weergavehiërarchie van de invoer, het kan de cursor niet besturen en kan geen tekst selecteren. Het aangepaste toetsenbord kan ook niets boven de bovenste rij weergeven. Het systeemtoetsenbord is niet beperkt door deze beperkingen. Het toont bijvoorbeeld een extensie wanneer u op een toets tikt om de gebruiker te laten zien op welke toets is getikt.

De rode lijn geeft de bovenlimiet van een aangepast toetsenbord weer.

sandboxing

Standaard heeft een toetsenbord geen netwerktoegang en kan het geen bestanden delen met de bijbehorende app. Om deze mogelijkheden in te schakelen, stelt u de waarde van de RequestsOpenAccess toets in de Info.plist bestand naar JA. Als u dit doet, wordt de sandbox van het toetsenbord groter, zoals beschreven in Apple's App Extension Programming Guide.

Als u om open toegang vraagt, krijgt uw toetsenbord de volgende mogelijkheden, elk met de volgende verantwoordelijkheid:

  • toegang tot locatieservices en de adresboekdatabase, die elk de toestemming van de gebruiker vereisen bij eerste toegang
  • optie om een ​​gedeelde container te gebruiken met de app van het toetsenbord, die functies inschakelt, zoals het bieden van een aangepaste gebruikersinterface voor lexiconbeheer in de bevattende app
  • mogelijkheid om toetsaanslagen en andere invoergebeurtenissen te verzenden voor verwerking op de server
  • toegang tot iCloud, die u bijvoorbeeld kunt gebruiken om ervoor te zorgen dat de toetsenbordinstellingen en uw aangepaste lexicon van autocorrecties up-to-date zijn op alle apparaten die eigendom zijn van de gebruiker
  • toegang tot Game Center en in-app-aankopen via de bevattende app
  • mogelijkheid om met beheerde apps te werken als u uw toetsenbord ontwerpt om mobiel apparaatbeheer (MDM) te ondersteunen

Lees het Apple's Designing for User Trust-document, waarin uw verantwoordelijkheden voor het respecteren en beschermen van gebruikersgegevens worden beschreven voor het geval u open toegang aanvraagt.

3. Hoe het werkt

In de meest eenvoudige vorm hebben we een applicatie die een toetsenborduitbreiding en een bevat UIInputViewController die het toetsenbord bestuurt en reageert op gebruikersgebeurtenissen.

De Aangepast toetsenbord sjabloon bevat een subklasse van UIInputViewController, Dit is de primaire weergavecontroller van je toetsenbord. Laten we naar de interface kijken om een ​​idee te krijgen van hoe het werkt.

class UIInputViewController: UIViewController, UITextInputDelegate, NSObjectProtocol var inputView: UIInputView! var textDocumentProxy: NSObject! get func dismissKeyboard () func advanceToNextInputMode () // Dit levert geen volledige repository op van de vocabulaire van een taal. // Het is uitsluitend bedoeld als aanvulling op bestaande lexicons. func requestSupplementaryLexiconWithCompletion (completionHandler: ((UILexicon!) -> Void)!) 
  • inputView is de weergave die wordt gebruikt voor het toetsenbord, het is hetzelfde als het uitzicht eigendom
  • dismissKeyboard methode kan worden aangeroepen om het toetsenbord te negeren
  • advanceToNextInputMode wordt gebruikt om te schakelen tussen toetsenborden
  • textDocumentProxy is het object dat u gebruikt om te communiceren met de huidige tekstinvoer
self.textDocumentProxy.insertText ("Tuts +") // voegt de tekenreeks "Tuts +" in het invoegpunt self.textDocumentProxy.deleteBackward () // Wist het teken links van het invoegpunt 
  • UIInputViewController voldoet aan de UITextInputDelegate protocol, u op de hoogte wanneer de tekst of tekstselectie via de de verandert selectionWillChangeselectionDidChangetextWillChange en textDidChangeevents

4. Een rekenmachinetoetsenbord maken

Laten we een aangepast toetsenbord maken om dit allemaal een beetje tastbaarder te maken. We maken een eenvoudig toetsenbord dat numerieke invoer en eenvoudige bewerkingen aankan. We gaan een XIB-bestand gebruiken voor de gebruikersinterface van het toetsenbord.

Stap 1: Maak een nieuw project

Open Xcode 6, maak een nieuwe aan Toepassing enkele weergave en selecteer Snel als de programmeertaal. Noem maar op CalculatorKeyboard.

Stap 2: voeg een tekstveld toe

Open Main.storyboard en sleep een tekstveld van de Objectenbibliotheek. We zullen dit gebruiken om het toetsenbord later te testen. Centreer het tekstveld en voeg de nodige lay-outbeperkingen toe zoals hieronder getoond.

Als je belt textField.becomeFirstResponder () in viewDidLoad het toetsenbord wordt geopend wanneer u de app start.

Stap 3: voeg de uitbreiding van het toetsenbord toe

Selecteer het projectbestand in de Project Navigator en voeg een nieuw doel toe door op de plusknop onderaan te klikken.

kiezen Application Extension aan de linkerkant, kies de Aangepast toetsenbord sjabloon, en noem het Rekenmachine.

Hiermee wordt een nieuwe groep met de naam gemaakt Rekenmachine, bevat twee bestanden KeyboardViewController.swift en Info.plist.

Stap 4: Opschonen

Open KeyboardViewController.swift. Het sjabloonklavier heeft één knop, waardoor de gebruiker kan schakelen tussen toetsenborden. Verwijder de code in de viewDidLoad methode.

Stap 5: De gebruikersinterface maken

Klik met de rechtermuisknop op de Rekenmachine groeperen en selecteren Nieuw bestand… . Selecteer de Gebruikersomgeving sectie aan de linkerkant, kies de Uitzicht sjabloon, en noem het Rekenmachine. Dit zou een bestand moeten maken met de naam Calculator.xib.

Open het XIB-bestand en, in de Kenmerken Inspector aan de rechterkant, stel de grootte in op Vrije vorm en de statusbalk naar Geen.

In de Size Inspector stel de breedte van de weergave in 320 en de hoogte tot 160.

Sleep een knop van de Objectenbibliotheek naar het uitzicht. In de Kenmerken Inspector, stel de titel in 1. In de Size Inspector, stel de breedte en hoogte van de knop in op 30. Verplaats de knop naar de rechterbovenhoek van de weergave totdat deze is uitgelijnd met de marges.

Kopieer de knop door op de knop te klikken en deze te verslepen terwijl u op de knop drukt Keuze sleutel. Plaats de tweede knop onder de eerste.

Selecteer de knoppen door op te drukken Command-A en kopieer de knoppen. Plaats de nieuwe knoppen onder de eerste en tweede knop.

Herhaal het proces om een ​​andere kolom met knoppen te maken totdat u vier kolommen met knoppen hebt.


Selecteer vervolgens de kolom aan de linkerkant en maak een kopie die uitlijnt met de linkerrand van de weergave.

Stel de breedte van de knoppen in op 140 punten. Vervang de knop linksboven door een label dat hetzelfde formaat heeft als de knop. Hernoem de knoppen zoals in de onderstaande schermafbeelding.

Geef de weergave een blauwachtige achtergrondkleur en stel de achtergrondkleur voor de knoppen in op wit met een dekking van 15%. En voor het weergavelabel, maak het zwart met een dekking van 15%. Zet de tekstgrootte op 18 punten voor elk gebruikersinterface-object en stel de tekstkleur in op wit. De gebruikersinterface zou er nu als volgt uit moeten zien:

Stap 6: De gebruikersinterface laden

We moeten eerst een property maken om de gebruikersinterface op te slaan.

class KeyboardViewController: UIInputViewController var calculatorView: UIView! ... 

Maak een methode met de naam loadInterface en noem het in de viewDidLoad methode van de KeyboardViewController.

class KeyboardViewController: UIInputViewController ... override func viewDidLoad () super.viewDidLoad () loadInterface () func loadInterface () // laad het nib-bestand var calculatorNib = UINib (nibName: "Calculator", bundel: nihil) // instantiate de weergave calculatorView = calculatorNib.instantiateWithOwner (self, options: nil) [0] as UIView // voeg de interface toe aan de hoofdweergave view.addSubview (calculatorView) // kopieer de achtergrondkleurweergave.backgroundColor = calculatorView.backgroundColor ... 

Stap 7: Het toetsenbord testen

Op dit punt zou je je nieuwe toetsenbord moeten kunnen testen. Met de CalculatorKeyboard schema geselecteerd, bouw en voer de applicatie uit op uw apparaat. Hiermee wordt een nieuw toetsenbord aan uw apparaat toegevoegd. Voordat u het echter kunt gebruiken, moet u het eerst installeren.

Ga naar instellingen > Algemeen > Toetsenbord > Toetsenborden en selecteer Voeg nieuw toetsenbord toe. Daar vind je de Rekenmachine toetsenbord in de lijst met toetsenborden van derden. Selecteer en installeer het toetsenbord. De volgende keer dat u het toetsenbord opent, moet u uw nieuwe toetsenbord kunnen zien door op de volgende toetsenbordknop te drukken.

Als u de iOS-simulator gebruikt, werkt het aangepaste toetsenbord mogelijk niet in uw app. Om het toetsenbord te zien, druk je op Home en open je Spotlight.

Stap 8: Volgend toetsenbord

Maak een eigenschap voor de volgende toetsenbordknop in de KeyboardViewController klasse.

class KeyboardViewController: UIInputViewController @IBOutlet var nextKeyboardButton: UIButton! ... 

Open Calculator.xib , kiezen Bestand eigenaar, en in de Identiteitsinspecteur verander zijn klasse in KeyboardViewController.

Klik met de rechtermuisknop op de Volgend toetsenbord knop en verbind een verwijzingspunt met de Bestand eigenaar.

In de loadInterface methode, we voegen een actie toe aan de nextKeyboard knop zoals hieronder weergegeven.

class KeyboardViewController: UIInputViewController ... func loadInterface () ... // Hierdoor wordt de knop call advanceToNextInputMode () aangeroepen bij nextKeyboardButton.addTarget (self, action: "advanceToNextInputMode", forControlEvents: .TouchUpInside)

Stap 9: Nummerweergave

Maak een eigenschap voor het display en verbind de referencing-uitgang in Interface Builder.

class KeyboardViewController: UIInputViewController @IBOutlet var display: UILabel! ...

Maak een methode met de naam clearDisplay en noem het in de viewDidLoad methode, na aanroepen loadInterface. Het display zou nu moeten verschijnen 0 wanneer u het toetsenbord opent.

class KeyboardViewController: UIInputViewController ... override func viewDidLoad () super.viewDidLoad () loadInterface () clearDisplay () ... @IBAction func clearDisplay () display.text = "0"

Verbind de C toetsen raak binnen aan evenement voor de clearDisplay methode in Interface Builder.

Stap 10: Nummerinvoer

Tijd om numerieke invoer te verwerken. Wanneer u het toetsenbord opent, wordt dit weergegeven 0 op het scherm. Als u op een cijfertoets tikt, moet het display naar dat nummer worden vervangen. Maak een eigenschap met de naam shouldClearDisplayBeforeInserting om dit gedrag te implementeren.

Maak een methode met de naam didTapNumber en verbind het in Interface Builder met alle cijferknoppen voor de raak binnen aan evenement. De methode gebruikt de titleLabel van de knop om te bepalen welk nummer is aangeboord.

class KeyboardViewController: UIInputViewController var shouldClearDisplayBeforeInserting = true ... @IBAction func didTapNumber (number: UIButton) if shouldClearDisplayBeforeInserting display.text = "" shouldClearDisplayBeforeInserting = false if var numberAsString = number.titleLabel? .text var numberAsNSString = numberAsString as NSString if var oldDisplay = display? .text! display.text = "\ (oldDisplay) \ (numberAsNSString.intValue)" else display.text = "\ (numberAsNSString.intValue)" 

Werk het clearDisplay methode zoals hieronder getoond.

class KeyboardViewController: UIInputViewController ... @IBAction func clearDisplay () display.text = "0" shouldClearDisplayBeforeInserting = true

De toetsenbordcode bevindt zich in een ander doel dan uw app. Hierdoor zijn de logboeken voor foutopsporing niet zichtbaar. Om de logboeken voor de te bekijken Rekenmachine doel, open het systeemlogboek van de iOS Simulator.

Stap 11: Puntinvoer

De knop om een ​​punt in te voegen zou een punt aan het scherm moeten toevoegen, maar alleen als er nog geen punt aanwezig is.

class KeyboardViewController: UIInputViewController ... @IBAction func didTapDot () if let input = display? .text var hasDot = false voor ch in input.unicodeScalars if ch == "." hasDot = true break if hasDot == false display.text = "\ (input)."  

Stap 12: Tekst invoegen

De knop om tekst in te voegen moet de displaytekst van de rekenmachine toevoegen aan het invoegpunt. Om dit te doen, gebruiken we de textDocumentProxy eigenschap zoals hieronder getoond.

class KeyboardViewController: UIInputViewController ... @IBAction func didTapInsert () var proxy = textDocumentProxy als UITextDocumentProxy als let input = display? .text as String? proxy.insertText (invoer)

Stap 13: Operaties afhandelen

Omdat we een eenvoudig toetsenbord implementeren dat geen uitdrukkingsbomen ondersteunt, 1 + 2 * 3 zal gelijk zijn 9. We gaan een eenvoudiger model gebruiken waarin de calculator een intern geheugenslot heeft waarop het bewerkingen kan toepassen.

Laten we een eenvoudige invoer nemen om te begrijpen hoe het algoritme van de rekenmachine werkt:

  • gebruiker tikt 1, het display zou moeten veranderen van 0 naar 1
  • gebruiker tikt +, de rekenmachine moet onthouden om het volgende ingevoerde nummer toe te voegen aan 1
  • gebruiker tikt 2, het display zou moeten veranderen van 1 naar 2
  • gebruiker tikt *, het display en het interne geheugen van de rekenmachine zouden moeten veranderen naar 3, de rekenmachine moet onthouden om het interne geheugen te vermenigvuldigen met het volgende ingevoerde nummer
  • gebruiker tikt 3, het scherm zou moeten blijven 3
  • gebruiker tikt =, de rekenmachine moet de laatste bewerking toepassen en het display zou moeten veranderen in 9

opmerkingen:

  • de rekenmachine moet onthouden welke volgende bewerking moet worden toegepast
  • na het invoeren van een nummer als een bewerking of een gelijk aantal wordt ingedrukt, moet de calculator de laatst herinnerde bewerking toepassen
  • als de gebruiker twee of meer bewerkingen indrukt zonder een cijfer in te voeren, moet de rekenmachine de laatste onthouden
  • Nadat een bewerking is toegepast, moet het display worden bijgewerkt met het resultaat
  • Nadat een resultaat wordt weergegeven, moet het scherm worden gewist voordat een ander nummer wordt geschreven

Om de calculator te implementeren, hebben we het volgende nodig:

  • een intern geheugen eigenschap die het tijdelijke resultaat opslaat
  • een eigenschap die de nextOperation
  • een andere die onthoudt of het de nextOperation nadat een bewerking is ingedrukt
enum Bediening case Toevoegingsgeval Vermenigvuldigingsgeval Aftrekvak Indelingsgeval Geen class KeyboardViewController: UIInputViewController var internalMemory = 0.0 var nextOperation = Operation.None var shouldCompute = false ... 

Maak een methode met de naam didTapOperation en verbind het met de bedieningstoetsen raak binnen aan evenement in Interface Builder. De methode gebruikt de knoptitel om te bepalen welke bewerking is ingedrukt.

class KeyboardViewController: UIInputViewController ... @IBAction func didTapOperation (operation: UIButton) if shouldCompute computeLastOperation () als var op = operation.titleLabel? .text switch op case "+": nextOperation = Operation.Addition case "- ": nextOperation = Operation.Subtraction case" X ": nextOperation = Operation.Multiplication case"% ": nextOperation = Operation.Division default: nextOperation = Operation.None

Maak en implementeer de computeLastOperation methode.

class KeyboardViewController: UIInputViewController ... @IBAction func computeLastOperation () // vergeet niet te berekenen als een andere bewerking wordt ingedrukt zonder eerst een ander nummer in te voeren shouldCompute = false als var input = display? .text var inputAsDouble = (invoer als NSString). doubleValue var result = 0.0 // pas de bedieningsschakelaar nextOperation toe case. Aanvulling: result = internalMemory + inputAsDouble case. Subtractie: result = internalMemory - inputAsDouble case .Multiplication: result = internalMemory * inputAsDouble case .Division: result = internalMemory / inputAsDouble default : result = 0.0 nextOperation = Operation.None var output = "\ (result)" // als het resultaat een geheel getal is, wordt het decimaalteken niet weergegeven als output.hasSuffix (". 0") output = "\ ( Int (resultaat)) " // truncereng tot laatste vijf cijfers var components = output.componentsSeparatedByString (". ") If components.count> = 2 var beforePoint = components [0] var afterPoint = components [1] if afterPoint. lengthOfBytes UsingEncoding (NSUTF8StringEncoding)> 5 let index: String.Index = advance (afterPoint.startIndex, 5) afterPoint = afterPoint.substringToIndex (index) output = beforePoint + "." + afterPoint // update het display display.text = output // sla het resultaat op internMemory = resultaat // onthoud om het scherm leeg te maken voordat u een nieuw nummer invoegt shouldClearDisplayBeforeInserting = true

Werk het clearDisplayMethod zoals hieronder getoond. Wanneer de gebruiker begint met het schrijven van het eerste nummer, moet het interne geheugen worden ingesteld op 0 en nextOperation zou toevoeging moeten zijn. Op die manier onthoudt de rekenmachine het ingevoerde nummer nadat de gebruiker het eerste nummer heeft ingevoerd en op een bewerking drukt.

class KeyboardViewController: UIInputViewController ... @IBAction func clearDisplay () display.text = "0" internalMemory = 0 nextOperation = Operation.Addition shouldClearDisplayBeforeInserting = true

Stap 14: Afwerking

Laten we de gebruiken IBInspectable aangiftekenmerk om een ​​hoekradius toe te voegen aan de knoppen en het display. Maak eerst een subklasse van UIButton en UILabel.

class RoundButton: UIButton @IBInspectable var cornerRadius: CGFloat = 0 didSet layer.cornerRadius = cornerRadius class RoundLabel: UILabel @IBInspectable var cornerRadius: CGFloat = 0 didSet layer.cornerRadius = cornerRadius 

Selecteer in Interface Builder de knoppen en wijzig hun klasse in RoundButton in de Identiteitsinspecteur. In de Attributen-inspecteur, u zou het nieuwe hoekradiusattribuut moeten zien.

Doe hetzelfde voor het displaylabel. Uw toetsenbord zou er nu zo uit moeten zien.

Conclusie

U zou nu een aangepast toetsenbord in iOS kunnen maken met behulp van de app-extensie-API's. Houd er rekening mee dat elk aangepast toetsenbord een manier moet hebben om over te schakelen naar het volgende toetsenbord en dat uw toetsenbord geen verbinding kan maken met internet, geen locatiediensten kan openen of standaard met de bijbehorende app kan praten, maar u kunt deze functies wel aanvragen.

Het systeem gebruikt het standaardtoetsenbord voor beveiligde velden, zoals velden voor wachtwoorden en telefoonnummers. Vergeet niet dat de code voor het aangepaste toetsenbord in een ander doelwit woont. Hierdoor zijn de logboeken voor foutopsporing niet zichtbaar. Open het systeemlogboek van de iOS-simulator om ze te bekijken.