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.
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.
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.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:
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.
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
eigendomdismissKeyboard
methode kan worden aangeroepen om het toetsenbord te negerenadvanceToNextInputMode
wordt gebruikt om te schakelen tussen toetsenbordentextDocumentProxy
is het object dat u gebruikt om te communiceren met de huidige tekstinvoerself.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 selectionWillChange
, selectionDidChange
, textWillChange
en textDidChange
eventsLaten 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.
Open Xcode 6, maak een nieuwe aan Toepassing enkele weergave en selecteer Snel als de programmeertaal. Noem maar op CalculatorKeyboard.
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.
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.
Open KeyboardViewController.swift. Het sjabloonklavier heeft één knop, waardoor de gebruiker kan schakelen tussen toetsenborden. Verwijder de code in de viewDidLoad
methode.
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:
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 ...
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.
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)
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.
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.
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)."
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)
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:
1
, het display zou moeten veranderen van 0
naar 1
+
, de rekenmachine moet onthouden om het volgende ingevoerde nummer toe te voegen aan 1
2
, het display zou moeten veranderen van 1
naar 2
*
, 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 nummer3
, het scherm zou moeten blijven 3
=
, de rekenmachine moet de laatste bewerking toepassen en het display zou moeten veranderen in 9
opmerkingen:
Om de calculator te implementeren, hebben we het volgende nodig:
intern geheugen
eigenschap die het tijdelijke resultaat opslaatnextOperation
nextOperation
nadat een bewerking is ingedruktenum 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
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.
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.