Site icon AppTractor

Строки в Swift выглядят одинаково, но не являются таковыми?

Недавно я столкнулся с проблемой, которая вызвала у меня недоумение. Две одинаковые строки отличались друг от друга. Как такое может быть?

Рассмотрим следующий код:

print("String1: '\(string1)'")
print("String2: '\(string2)'")

print(string1 == string2)

Получаем следующий вывод:

String1: '123456'
String2: '123456'
false

Что? Я просто читал строки из файла. Я начал сомневаться в реальности. Строки были одинаковыми и в то же время разными.

Я решил попробовать избавиться от странных символов пробела:

let trimmed1 = string1.trimmingCharacters(in: .whitespacesAndNewlines)
let trimmed2 = string2.trimmingCharacters(in: .whitespacesAndNewlines)

print("String1: '\(trimmed1)'")
print("String2: '\(trimmed2)'")

print(trimmed1 == trimmed2)

Нет:

String1: '123456'
String2: '123456'
false

В конце концов я немного покопался во внутренностях и открыл для себя радости невидимого знака порядка байтов \u{FEFF}.

Мои строки действительно содержали его (хотя, поскольку я читал их из файла, это было неочевидно):

let string1 = "\u{FEFF}123456"
let string2 = "123456"

Теперь у меня есть удобное расширение:

extension String {
    
    var withoutBOM: String {
        let bom = "\u{FEFF}"
        if hasPrefix(bom) {
            return String(dropFirst(bom.count))
        }
        return self
    }
}

trimmingCharacters(in: .controlCharacters) тоже справляется с этой задачей:

import Foundation

let string1 = "\u{FEFF}123456"
let string2 = "123456"

let trimmed1 = string1.trimmingCharacters(in: .controlCharacters)
let trimmed2 = string2.trimmingCharacters(in: .controlCharacters)

print("String1: '\(trimmed1)'")
print("String2: '\(trimmed2)'")

print(trimmed1 == trimmed2)
String1: '123456'
String2: '123456'
true

Ух ты! Вселенная снова внутренне непротиворечива (я думаю).

Exit mobile version