Nach dem Update auf Xcode 11.2 stürzt die App ab: So besiegen Sie _UITextLayoutView
\n\nKennt man das: Sie arbeiten ruhig an Ihrem Projekt, alles läuft, Tests bestehen, Benutzer sind zufrieden. Und dann – peng! – Sie aktualisieren Xcode auf Version 11.2, starten die App, und sie stürzt mit einem mysteriösen Fehler _UITextLayoutView ab. Kommt Ihnen bekannt vor? Wenn ja – Sie sind nicht allein. Dieses Problem hat Stack Overflow Ende 2019 buchstäblich in die Luft gesprengt (tausende Aufrufe pro Woche).
In diesem Artikel zeige ich Ihnen nicht nur, wie Sie diesen Bug beheben, sondern erkläre auch, warum er auftritt, wie Sie ihn diagnostizieren und, vor allem, wie Sie ihn in Zukunft verhindern können. Wir analysieren alles anhand von Live-Beispielen in Swift. Los geht's!
\n\nWas für ein Tier ist _UITextLayoutView?
\n\nBeginnen wir mit der Theorie. _UITextLayoutView ist eine interne (private) Klasse von UIKit, die für das Rendern von Text in UITextView verantwortlich ist. Apple dokumentiert sie nicht öffentlich, daher waren Entwickler ratlos, als in Xcode 11.2 etwas mit dieser Klasse schiefging. Der Fehler sieht in etwa so aus:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_UITextLayoutView setFrame:]: unrecognized selector sent to instance 0x...'\n\nDer Schlüsselsatz ist "unrecognized selector sent to instance". Das bedeutet, dass Sie versuchen, die Methode setFrame: bei einem Objekt aufzurufen, das sie nicht unterstützt. Und da _UITextLayoutView eine private Klasse ist, verhielt sie sich vor Xcode 11.2 anders.
Wer ist gefährdet?
\n\nDas Problem tritt nicht bei allen auf, sondern nur unter bestimmten Bedingungen. Hier ist ein typisches Szenario:
\n- \n
- Sie verwenden
UITextViewmit aktivierter automatischer Größenanpassung (auto-sizing). \n - Sie haben eine benutzerdefinierte View-Hierarchie, in der
UITextViewinUIScrollViewoderUITableViewCellverschachtelt ist. \n - Sie interagieren aktiv mit dem Textfeld: scrollen, bearbeiten, Schriftart ändern. \n
Wenn mindestens ein Punkt zutrifft – herzlichen Glückwunsch, Sie sind gefährdet. Aber keine Sorge: Es gibt eine Lösung, und sie ist elegant.
\n\nSchritt 1: Diagnose – Finden Sie den Übeltäter
\n\nBevor wir behandeln, stellen wir sicher, dass das Problem tatsächlich bei _UITextLayoutView liegt. Öffnen Sie die Xcode-Konsole (View → Debug Area → Activate Console) und starten Sie die App. Wenn Sie einen Fehler sehen, der dem oben genannten ähnelt – sind Sie auf dem richtigen Weg.
Ein zusätzliches Anzeichen: Der Crash tritt beim ersten Versuch auf, UITextView anzuzeigen oder beim Scrollen darin. Wenn die App direkt nach dem Laden abstürzt – ist es höchstwahrscheinlich dieser Fehler.
Schritt 2: Einfache und schnelle Lösung (für Eilige)
\n\nDer beliebteste Fix auf Stack Overflow ist, die automatische Größenanpassung bei UITextView zu deaktivieren. So geht's:
// In Ihrem viewDidLoad oder der Setup-Methode\ntextView.isScrollEnabled = false\ntextView.translatesAutoresizingMaskIntoConstraints = true\n\nAber Achtung! Diese Lösung funktioniert, aber sie zerstört die automatische Größe des Textes. Wenn es für Sie kritisch ist, dass UITextView die Höhe dynamisch an den Inhalt anpasst – ist diese Variante nicht geeignet. Lassen Sie uns tiefer graben.
Schritt 3: Fortgeschrittene Lösung – Überschreiben von layoutSubviews
\n\nApple hat in Xcode 11.2.1 einen Patch veröffentlicht. Aber wenn Sie aus irgendeinem Grund bei 11.2 geblieben sind oder eine universelle Lösung wünschen, müssen Sie Folgendes tun.
\n\nErstellen Sie eine Unterklasse von UITextView und überschreiben Sie die Methode layoutSubviews:
import UIKit\n\nclass FixedTextView: UITextView {\n override func layoutSubviews() {\n super.layoutSubviews()\n // Entfernen Sie überflüssige Subviews aus der Ebene, die der Bug verursacht\n self.subviews.forEach { subview in\n if subview.isKind(of: NSClassFromString("_UITextLayoutView") ?? UIView.self) {\n