Как определить количество отображаемых строк Swift? - PullRequest
2 голосов
/ 20 июня 2019

Я рассмотрел такие вопросы, как Получите длину строки и Почему символы эмодзи, такие как ?‍?‍?‍?, так странно трактуются в строках Swift? , но ни то, ни другоеохватывают этот конкретный вопрос.

Все началось с попытки применить модификаторы тона кожи к символам эмодзи (см. Добавление модификатора тона кожи к эмодзи программно ).Это привело к удивлению, что происходит, когда вы применяете модификатор тона кожи к обычному символу, такому как "A".

Примеры:

let tonedThumbsUp = "?" + "?" // ??
let tonedA = "A" + "?" // A?

Я пытаюсь обнаружить этот второй случай.count обеих этих строк равно 1. И unicodeScalars.count равно двум для обоих.

Как определить, отображается ли получающаяся строка как один символ при отображении?Другими словами, как я могу определить, применялся ли модификатор тона кожи для создания одного символа или нет?

Я пробовал несколько способов вывести информацию о строке, но ни один из них не дал желаемого результата.

func dumpString(_ str: String) {
    print("Raw:", str, str.count)
    print("Scalars:", str.unicodeScalars, str.unicodeScalars.count)
    print("UTF16:", str.utf16, str.utf16.count)
    print("UTF8:", str.utf8, str.utf16.count)
    print("Range:", str.startIndex, str.endIndex)
    print("First/Last:", str.first == str.last, str.first, str.last)
}

dumpString("A?")
dumpString("\u{1f469}\u{1f3fe}")

Результаты:

Raw: A? 1
Scalars: A? 2
UTF16: A? 3
UTF8: A? 3
First/Last: true Optional("A?") Optional("A?")
Raw: ?? 1
Scalars: ?? 2
UTF16: ?? 4
UTF8: ?? 4
First/Last: true Optional("??") Optional("??")

Ответы [ 2 ]

2 голосов
/ 20 июня 2019

Что произойдет, если вы напечатаете ?? в системе, которая не поддерживает модификаторы Фитцпатрика? Вы получаете ?, а затем все, что система использует для заполнителя неизвестного символа.

Так что я думаю, чтобы ответить на этот вопрос, вы должны проконсультироваться с наборщиком вашей системы. Для платформ Apple вы можете использовать Core Text, чтобы создать CTLine, а затем сосчитать количество глифов строки. Пример:

import Foundation
import CoreText

func test(_ string: String) {
    let richText = NSAttributedString(string: string)
    let line = CTLineCreateWithAttributedString(richText as CFAttributedString)
    let runs = CTLineGetGlyphRuns(line) as! [CTRun]
    print(string, runs.count)
}

test("?" + "?")
test("A" + "?")
test("B\u{0300}\u{0301}\u{0302}" + "?")

Вывод с игровой площадки macOS в Xcode 10.2.1 на macOS 10.14.6 Beta (18G48f):

?? 1
A? 2
B̀́̂? 2
0 голосов
/ 20 июня 2019

Я думаю, что можно подумать об этом, посмотрев, присутствует ли модификатор и, если да, увеличил ли он количество символов.

Так, например:

let tonedThumbsUp = "?" + "?"
let tonedA = "A" + "?"
tonedThumbsUp.count // 1
tonedThumbsUp.unicodeScalars.count // 2
tonedA.count //2
tonedThumbsUp.unicodeScalars.count //2
let c = "\u{1F3FB}"
tonedThumbsUp.contains(c) // true
tonedA.contains(c) // true

Хорошо, так что они оба содержат символ-модификатор, и оба содержат два скаляра Юникода, но один - счет 1, а другой - счет 2. Конечно, это полезное различие.

...