Argh! NSXMLParser does not support reentrant parsing

Schlimm genug, dass die Render-Engine von Argh! Earthlings! seit Monaten durch die Mangel gedreht werden, muss um den Autopiloten zu stabilisieren, nun bockt auch der NSXMLParser.

Wasnlos?

Mit dem Update auf iOS 8 wurden Bugs in der Klasse NSXMLParser beseitigt, die das Projekt nicht mehr kompilieren lassen. Ersten Erkenntnissen nach wurde am Thread-Verhalten des Parser geschraubt, mit der Folge, dass diese hübsche Message erscheint:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
	reason: 'NSXMLParser does not support reentrant parsing.'

Das Web gibt bis hierher wenig Aufschluss, was defekt sein könnte. Einige Lösungen passen nicht auf mein Vorgehen. Mein Parser ist vom NSXMLParser abgeleitet und eigentlich recht simpel.

Was Xcode beim Build nun stört ist die Tatsache, dass ich 2 Instanzen des NSXMLParsers in einander geschachtelt habe:

  • Parser A kümmert sich um die Auswertung des Skelett-Abbilds von Objekten, z.B. Figuren.
  • Parser B baut die Fähigkeiten der Objekte aus. Bei Figuren sind dies ihre Handlungen, wie nehmen, schauen etc.
  • Parser A delegiert unbekannte XML-Tags an Parser B weiter, in der Hoffnung, dass dieser die Aufgabe stemmen kann.

Das ist offenbar nicht mehr möglich.

Wofür die Parsing-Kette?

Da auch ein Raum gewisse "Fähigkeiten" hat, wollte ich dem Parser C für Räume die Möglichkeit geben den gleichen Code über den Parser B zu laden.

Ziel: Single Responsibility-Principle und Don't Repeat Yourself-Principle durch Komposition der Parser.

Lösungsansatz

Das Konzept sieht zukünftig vor, dass der Parser vom Rest der Parsing-Logik entkoppelt werden sollte. Es sollte möglich sein, die Parsing-Engine in neutrale Objekte zu extrahieren und so deren Instanzen beliebig oft an einen "einzigen" NSXMLParser zu koppeln.

Richtig instanziiert, sollte es auch in einer Multi-Threaded Umgebung möglich sein, Skelette und Räume unbeschadet zu laden.

Problem

Der selbe, fehlerhafte Zustand tritt auch ein, wenn eine Raum-Konfiguration das Laden von Objekten anfordert, wie z.B. von Figuren oder Szenenelementen. Diese haben eigene Parser, was wieder eine Verschachtelung erzwingt.

Lösungsansatz

Die Parser müssen entweder im eigenen Thread aufgerufen, oder seriell abgearbeitet werden. Letztes wäre einfacher, verlangt aber nach einem kompletten Redesign des Ladeprozesses.

Let's do it!