Nach Xcode 11.2: App stürzt wegen _UITextLayoutView ab – Lösung

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Nach dem Update auf Xcode 11.2 stürzt die App ab: So besiegen Sie _UITextLayoutView

\n\n

Kennt 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).

\n\n

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\n

Was für ein Tier ist _UITextLayoutView?

\n\n

Beginnen 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:

\n\n
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_UITextLayoutView setFrame:]: unrecognized selector sent to instance 0x...'
\n\n

Der 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.

\n\n

Wer ist gefährdet?

\n\n

Das Problem tritt nicht bei allen auf, sondern nur unter bestimmten Bedingungen. Hier ist ein typisches Szenario:

\n
    \n
  • Sie verwenden UITextView mit aktivierter automatischer Größenanpassung (auto-sizing).
  • \n
  • Sie haben eine benutzerdefinierte View-Hierarchie, in der UITextView in UIScrollView oder UITableViewCell verschachtelt ist.
  • \n
  • Sie interagieren aktiv mit dem Textfeld: scrollen, bearbeiten, Schriftart ändern.
  • \n
\n\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\n

Schritt 1: Diagnose – Finden Sie den Übeltäter

\n\n

Bevor 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.

\n\n

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.

\n\n

Schritt 2: Einfache und schnelle Lösung (für Eilige)

\n\n

Der beliebteste Fix auf Stack Overflow ist, die automatische Größenanpassung bei UITextView zu deaktivieren. So geht's:

\n\n
// In Ihrem viewDidLoad oder der Setup-Methode\ntextView.isScrollEnabled = false\ntextView.translatesAutoresizingMaskIntoConstraints = true
\n\n

Aber 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.

\n\n

Schritt 3: Fortgeschrittene Lösung – Überschreiben von layoutSubviews

\n\n

Apple 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\n

Erstellen Sie eine Unterklasse von UITextView und überschreiben Sie die Methode layoutSubviews:

\n\n
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                

Blogs

Buchempfehlungen