Skip to content
PressboardKit
FAQBrowse docs

Reference

FAQ

The questions that come up while integrating — Full Access, the translucent backdrop, memory, in-app use, testing, and what the engine does not do for you.

Does it need Full Access?

Only for haptics. hapticFeedback needs RequestsOpenAccess, and so does cursorDragEngageHaptic; without it the system silently ignores the request. Everything else — typing, autocorrection, suggestions, emoji, slide-to-type, the key click sound — works without it.

The key sound is worth calling out, because it is usually the reason people ask. The engine plays the system keyboard click itself through AudioServicesPlaySystemSound, so there is no host setup and no Full Access involved, and it respects the silent switch. The Simulator does not play those clicks at all — test key sound on a device.

My keyboard is an opaque grey rectangle. Why?

Something behind the SwiftUI view is opaque. With translucentBackground on, the engine draws its own background fully clear so the system’s translucent backdrop shows through — but the default input view is not clear, and it sits in front of that backdrop.

host.view.backgroundColor = .clear
view.backgroundColor = .clear
host.view.clipsToBounds = false
view.clipsToBounds = false

PressboardInputViewController does this for you. If you are hosting the SwiftUI view yourself, you have to. See Theming.

Note also that a non-native theme deliberately turns the glass off — a solid theme would be hidden behind it.

Can I use a UIVisualEffectView instead?

No, and it is worth knowing why. A custom keyboard is not given the host app’s rendered content, so a material has nothing to blur. It paints a flat grey veil, which reads as exactly the rectangle you were trying to avoid. Clearing everything and relying on the system backdrop is what the native keyboard does.

The top row’s key-pop is cut off at the top edge.

An extension cannot draw outside its own frame — the system clips it, and un-clipping the system’s container views does not help. Reserve the overflow as headroom inside a slightly taller keyboard instead: pass it to PressboardKeyboardView(topInset:) and add the same amount to your input view’s height. NativeMetrics.popOverflow(for:) gives you the amount for the active preview style. The controller exposes it as popTopInset.

Does the engine touch my text document?

No. The view reports KeyboardAction values and never writes anything. That is deliberate: it keeps the engine host-agnostic, and it means you can intercept any input before it lands. PressboardKitApp adds a controller that does own the editing, through a PressboardTextDocument you hand it — but the core engine does not.

Can I use it inside my app, without a keyboard extension?

Yes. Point a PressboardController at any PressboardTextDocumentStringTextDocument is the in-memory one — and render PressboardRootView. See the quick start.

That is also the fastest way to iterate on look and behaviour. It is not a substitute for testing the real extension: an in-app preview runs in your process, the real extension is hosted out of process, and touch handling, hit-testing and the backdrop all differ there.

PressboardKitApp alone, if you are subclassing PressboardInputViewController — it depends on the other four. Otherwise PressboardKit plus PressboardKitLayouts, with PressboardKitAutocomplete and PressboardKitEmoji added only if you use them. They are separate products because an extension’s memory budget is a fraction of an app’s.

Does slide-to-type work without the autocomplete module?

The decoder is in the core module, but it decodes against a candidate word list, and that list comes from a provider. Without PressboardKitAutocomplete or a provider of your own, there is nothing to decode against.

How do settings from my app reach the keyboard?

Through an App Group. KeyboardBehavior is Codable; persist it in a suite both targets can see and pass loadBehavior / saveBehavior to PressboardConfiguration. The controller reloads on viewWillAppear and saves on every change. Full setup in Installation.

Will an SDK update reset my users’ settings?

No. KeyboardBehavior decodes forward-compatibly — every key is optional and falls back to its default — so a release that adds a property leaves stored settings intact. With synthesised Codable it would not: one added property would make every previously stored value fail to decode at once.

Why does the number pad layout never appear?

iOS does not present a third-party keyboard for .numberPad, .phonePad or .decimalPad fields; it shows its own pad. Those layouts only apply when you embed the engine as an in-app keyboard. Over such a field the suggestion bar is also suppressed, because native shows none.

The caret disappears while dragging on the space bar.

Leave cursorDragUpdateInterval at its default. Every caret move is a call across a process boundary, and a high-refresh display produces them faster than the app you are typing into can repaint — push them all and the text view never gets an idle moment to draw the caret. The default coalesces them, which leaves those gaps. 0 restores per-step pushing, which is what native does — but native is not talking across a process boundary.

Can I add a language?

Adding a language is a data-table change inside PressboardKitLayouts — the letter rows, the callouts, the locale case — not an engine change, and one we would rather make for you than have you fork over. KeyboardLocale already carries 73 cases. Supplying a different word list for an existing language is injection, and goes through PressboardConfiguration(words:). See Layouts and languages.

Is the keyboard accessible?

Every key is published as one accessibility element carrying a name — the character in its current case, or space, delete, shift, return, letters, next keyboard, dictate for the control keys — the .isKeyboardKey trait, so iOS applies VoiceOver’s typing modes, and an activation action that types the key directly. Assistive activation delivers no touches, so without that action neither input pipeline would see anything at all.

Nothing is required of a host for this. If you pass a keyOverlay, it is hidden from assistive technology automatically so it cannot turn the key into a container and swallow its name.

How do I test touch behaviour?

Not in the in-app preview. An in-app preview runs in your process and the real keyboard does not, and behaviour that works in the first has repeatedly failed in the second — which is a thing worth knowing before you spend a day on it.

Every key carries a stable accessibility identifier — key.character.s, key.shift, key.space and so on — so an XCUITest can look up a key’s real rendered rect and tap absolute points inside it. That is the only way to prove a hit-test in the real, out-of-process extension. One trap worth knowing: a build system will happily run a stale extension binary, so uninstall the app before an A/B measurement rather than trusting that a rebuild took effect.

Do I need a licence, and what does it cost?

Yes, and nothing. PressboardKit is free — there is no charge for a licence and no tier above it — but it is licensed rather than open source. Register an application by product name and bundle identifier and a licence is issued against it. Full detail on Licensing.

Is there a licence check in the engine?

Not today. The core module carries a LicenseGate seam, but its default, .unrestricted, unlocks every feature. It takes a closure rather than a licence key: there is no activation API to call, and no code change to make. A later build will validate an issued licence at setup, additively. See Licensing.

Something is missing from these docs.

The source is the contract: KeyboardBehavior.swift for the parameters, PressboardController.handle(_:) for a complete action router, and the demo app in the repository for a working extension, a settings screen and the UI test harness.

Edit this page on GitHub