После обновления Xcode до 11.2 приложение падает с ошибкой _UITextLayoutView при использовании UITextView
Причина проблемы
Ошибка _UITextLayoutView возникает из-за того, что в Xcode 11.2 Apple изменила внутреннюю реализацию UITextView. В новой версии фреймворка появился приватный класс _UITextLayoutView, который используется для рендеринга текста. Однако старые storyboard или XIB-файлы, созданные в Xcode 11.1, не содержат информации об этом классе, что и вызывает краш при деархивации.
Проблема усугубляется тем, что Xcode 11.2 автоматически обновляет storyboard при открытии, но не всегда корректно добавляет новый класс. Если вы используете Interface Builder, он может сохранить ссылки на старую архитектуру.
Решение 1: Очистка и пересборка проекта (самый простой способ)
Сделайте полную очистку проекта и удалите все кэши:
- Clean Build Folder:
Product→Clean Build Folder(илиCmd+Shift+K) - Удалите Derived Data:
Xcode→Preferences→Locations→ нажмите на стрелку рядом сDerived Dataи удалите папку - Удалите кэш Interface Builder:
~/Library/Caches/com.apple.dt.Xcode
После этого перезапустите Xcode и пересоберите проект. В большинстве случаев этого достаточно.
Решение 2: Изменение storyboard вручную (если первый способ не помог)
Откройте storyboard как исходный код (правой кнопкой мыши по файлу → Open As → Source Code). Найдите все вхождения UITextView и добавьте атрибут layoutManager:
<textView ...>
<layoutManager>
<layoutManager>
<textContainer>
<textContainer/>
</textContainer>
</layoutManager>
</layoutManager>
</textView>
Это заставит Interface Builder правильно инициализировать UITextView с новым классом. После сохранения файла откройте его снова в Interface Builder и проверьте, что всё работает.
Решение 3: Программное создание UITextView (рекомендуется для долгосрочной стабильности)
Если вы хотите избежать подобных проблем в будущем, создавайте UITextView программно, а не через storyboard:
import UIKit
class NoteViewController: UIViewController {
var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
setupTextView()
}
private func setupTextView() {
textView = UITextView(frame: view.bounds)
textView.text = "Заметка"
textView.font = UIFont.systemFont(ofSize: 16)
textView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(textView)
}
}
Это полностью исключает зависимость от версии Xcode и даёт больше контроля над поведением.
Решение 4: Обновление Xcode до последней версии
Apple исправила эту проблему в Xcode 11.2.1 и новее. Обновитесь через Mac App Store или загрузите последнюю версию с Apple Developer Portal.
Важно: Если вы работаете в команде, убедитесь, что все разработчики используют одинаковую версию Xcode, иначе storyboard могут конфликтовать.
<<Альтернативный подход: Использование XIB-файла вместо storyboard
Если вы не хотите переписывать весь код на программное создание, но storyboard продолжает падать, попробуйте вынести UITextView в отдельный XIB-файл. Это часто решает проблему, так как XIB-файлы менее подвержены багам при обновлении Xcode.
Создайте новый файл NoteView.xib, добавьте в него UITextView и подключите его через @IBOutlet. Затем загружайте вью из XIB:
class NoteViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
override func loadView() {
super.loadView()
let nib = UINib(nibName: "NoteView", bundle: nil)
let views = nib.instantiate(withOwner: self, options: nil)
if let view = views.first as? UIView {
self.view = view
}
}
}
Этот метод часто спасает, когда основной storyboard повреждён. Также рекомендуется удалить все UITextView из storyboard и добавить их заново в Interface Builder — иногда Xcode просто не обновляет старые объекты.
Если ничего не помогает, временно отключите UITextView в storyboard и замените его на UILabel с возможностью редактирования через код — это даст время дождаться исправления от Apple.