Swift y Objective-C

Longitud de String en Swift: mide hangul, emoji y bytes

Compara Character, escalares, UTF-16 y UTF-8; verifica claves hangul equivalentes y recorta un emoji familiar sin dividirlo.

2 min de lectura
Imagen de portada de Longitud de String en Swift: mide hangul, emoji y bytes

Elige la unidad antes de implementar un límite de texto. count en Swift mide Character, o clústeres de grafemas extendidos; los límites de transferencia suelen medir bytes. Un mismo carácter visible puede ocupar tamaños internos distintos.

Mecanismo y decisión de diseño

La sílaba hangul del experimento usa un escalar precompuesto o tres escalares jamo combinados. Swift String reconoce su equivalencia canónica, también al consultar un diccionario. Un emoji familiar reúne varios escalares en un Character. Contar otra unidad en otro lenguaje no es un error por sí mismo. Fuente primaria

Código reproducible

Los escapes Unicode fijan las entradas exactas. Compara cantidades de Character, escalares y bytes UTF-8 del hangul. Mide UTF-16 y UTF-8 del emoji, insértalo entre A y B y usa prefix y String.Index. Comprueba aparte el acceso a texto vacío.

Este ejemplo independiente se ejecutó el 2026-10-23 con Apple Swift 6.4 para arm64 macOS, en modo de lenguaje Swift 6. No necesita red ni paquetes adicionales.

Descargar el archivo Swift completo

Ejecuta el comando en la carpeta de descarga. Las precondiciones detienen la ejecución si falla una comprobación. No uses -Ounchecked: elimina estas comprobaciones.

swift -swift-version 6 swift-string-grapheme-cluster-indexing.swift
let composed = "\u{D55C}"
let decomposed = "\u{1112}\u{1161}\u{11AB}"
precondition(composed == decomposed)
precondition(composed.count == 1 && decomposed.count == 1)
precondition(composed.utf8.count == 3 && decomposed.utf8.count == 9)
precondition(decomposed.unicodeScalars.count == 3)
let lookup = [composed: 42]
precondition(lookup[decomposed] == 42)

let family = "\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}"
precondition(family.count == 1 && family.unicodeScalars.count == 7)
precondition(family.utf16.count == 11 && family.utf8.count == 25)
let text = "A" + family + "B"
precondition(text.count == 3 && String(text.prefix(2)) == "A" + family)
let second = text.index(after: text.startIndex)
precondition(String(text[second]) == family)
let empty = ""
precondition(empty.first == nil && empty.prefix(2).isEmpty)
print("hangul=characters:1,scalars:1/3,utf8:3/9 equal:true dictionary:42")
print("family=characters:1,scalars:7,utf16:11,utf8:25 prefix=2 empty=safe")

Salida registrada e interpretación

hangul=characters:1,scalars:1/3,utf8:3/9 equal:true dictionary:42
family=characters:1,scalars:7,utf16:11,utf8:25 prefix=2 empty=safe

Ambas formas hangul tienen un Character, pero usan 3 y 9 bytes UTF-8; la descompuesta tiene tres escalares. La clave equivalente devuelve 42. El emoji familiar tiene un Character, siete escalares, once unidades UTF-16 y veinticinco bytes UTF-8. prefix(2) conserva el emoji completo.

Alcance y limitaciones

Character no modela perfectamente toda noción humana de letra; importan reglas de segmentación y versiones Unicode. No supongas tres bytes por carácter hangul visible o emoji. Swift Dictionary no exige siempre normalización NFC explícita, pero hay que verificar contratos externos de comparación y codificación.

Qué comprobar después

Acuerda si los límites del servidor y cliente cuentan caracteres o bytes UTF-8. Usa API como prefix para vistas previas. Si repites accesos aleatorios, evalúa coste y memoria de convertir a array. El ejemplo Optional distingue texto ausente de texto vacío.

Experimento relacionado

Fuentes y verificación