Unicode Normalization Explains Why Backspace Sometimes Takes More Than One Tap
How NFC, NFD, and NFKC editing behavior
It can be confusing when deleting a single visible character requires two or more backspace taps. You press delete once, nothing seems to happen. Press again, and only then does the character disappear. This is not a keyboard bug. It is usually a consequence of Unicode composition and normalization.
In Swift, a String is a collection of extended grapheme clusters, not Unicode scalars or UTF-16 code units. What looks like one character on screen can be composed of multiple scalars. Normalization (NFC vs NFD) affects equality and storage. Compatibility normalization (NFKC) goes further: it folds compatibility characters into their canonical equivalents.
import Foundation
// Canonical normalization (NFC)
let decomposed = "e\u{0301}" // se + โฬ
let nfc = decomposed.precomposedStringWithCanonicalMapping
print(nfc.unicodeScalars.count) // 1
// Compatibility normalization (NFKC)
let ligature = "๏ฌ" // U+FB01 LATIN SMALL LIGATURE FI
print(ligature == "fi") // false
let nfkc = ligature.precomposedStringWithCompatibilityMapping
print(nfkc == "fi") // true
print(nfkc.unicodeScalars.map { $0.value }) // [102, 105]

