Неустранимая ошибка: недостаточно места для копирования содержимого строки (iOS 13) Emoji - PullRequest
1 голос
/ 09 октября 2019

После обновления до Xcode 11 и iOS 13 я начал постоянно получать эту ошибку:

Неустранимая ошибка: недостаточно места, выделенного для копирования содержимого строки

Мне удалосьсузить код, связанный с авариями, до этого небольшого фрагмента. Вы можете вставить его в приложение для iOS или даже на игровую площадку, и он вылетит:

// Test. This code crashes even in a playground.
let h = 3, w = 3
// No crash without "?" symbol!
let fieldStrings: [String] = ["?", "3", "3", "4", "1", "2", "2", "4", "2"]
let maxLength = fieldStrings.reduce(0) { (maxLength, s) in max(maxLength, s.count) }
print(maxLength) // 1
// No crash without padding!
let paddedFieldStrings = fieldStrings.map { s in
    s.padding(toLength: maxLength, withPad: " ", startingAt: 0)
}
var lines = [String]()
for y in 0..<h {
    var line = ""
    for x in 0..<(w - 1) {
        // CRASH HERE! x = 0, y = 0
        line += paddedFieldStrings[x * h + y] + "  "
    }
    line += paddedFieldStrings[(w - 1) * h + y]
    lines.append(line)
}

Оригинальный код отвечал за печать описания игрового поля. До iOS 13 все работало хорошо. Я заметил, что здесь необходимы две точки (помимо добавления строки):

  1. Символ «эмодзи» «страница с завитком» - U + 1F4C3
  2. padding(toLength:withPad)

Авария также повторяется с другими смайликами.

Я не думаю, что этот вопрос является дубликатом, потому что мой случай не включает многопоточность или базу данных. Так что, пожалуйста, не отмечайте.

Мне кажется, что это ошибка, и я сообщу об этом Apple, но сейчас нам нужно найти обходной путь.

Swift 5.

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Обходной путь:
Как мы все согласны - это системная ошибка. Обходной путь облегчения - изменить maxLength вычисление, заменив s.count на s.utf16.count:

let maxLength = fieldStrings.reduce(0) { (maxLength, s) in max(maxLength, s.utf16.count) }

Сбой вызван padding(toLength:withPad:startingAt:), когда toLength меньше длины соответствующегоNSString. NSString.length подразумевается здесь, потому что padding() является частью Фонда. utf16.count равно length соответствующего NSString. Хотя проблема скрывается внутри функции padding(), каким-то образом она молча возвращает недопустимую строку, а затем происходит сбой при операции +. Для получения дополнительной информации см. это обсуждение на форумах Swift .

0 голосов
/ 09 октября 2019

Это действительно может быть ошибка со стороны Apple.

Некоторый контекст ...

Разные представления смайликов имеют разную длину. Например, («as» как String) будет иметь длину (или count), равную 1, в то время как («?» как NSString) будет иметь длину 2 (см. эту ссылку для более подробной информации). объяснение).

Ваш код устанавливает maxLength в 1, потому что длина всех строк в вашем массиве, включая эмодзи, разрешается до 1. Однако это выглядит где-то в реализации padding,длина эмодзи равна 2. Итак, padding возвращает nil, когда вы передаете эмодзи, и maxLength = 1.

Вот пример кода, который поможет объяснить:

("?" as String).count // `count` is 1
("?" as NSString).length // `length` is 2

"?".padding(toLength: 1, withPad: " ", startingAt: 0) // returns nil
"?".padding(toLength: 2, withPad: " ", startingAt: 0) // returns "?"
"?".padding(toLength: 3, withPad: " ", startingAt: 0) // return "? "

Опять же, это немного подозрительно и кажется ошибкой со стороны Apple.

Тем временем, расчет maxLength с использованием max(maxLength, (s as NSString).length)) или даже просто обеспечение того, что maxLength больше 1 для любого массива, содержащего смайлики, должны исправить ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...