webentwicklung-frage-antwort-db.com.de

rekursiveDescription-Methode in Swift?

Gibt es eine Möglichkeit, [self.view recursiveDescription] in Swift zu verwenden? Ich versuche, diese Methode zu verwenden, erhalte jedoch die folgende Fehlermeldung:

'UIView' does not have a member named 'recursiveDescription'

Irgendwelche Vorschläge?

31
Vik Singh

Für den Zugriff auf die private/undokumentierte Objective-C-API (wie die -recursiveDescription-Methode für UIView) von Swift können Sie Folgendes ausführen:

  1. Erstellen Sie eine neue Objective-C-Kategorie in der Klasse, in der die private Methode definiert ist (z. B. UIView).
  2. Drücken Sie Yes , wenn Xcode Sie zur Konfiguration eines Bridging-Headers auffordert. (Wenn Sie bereits einen Bridging-Header in Ihrem Projekt haben, wird dieser Schritt übersprungen).
  3. Die Implementierungsdatei (.m) der Kategorie kann entfernt werden.
  4. Deklarieren Sie die private Methode im Kategorieheader:

    // UIView+Debugging.h
    
    @interface UIView (Debugging)
    - (id)recursiveDescription;
    @end
    

Jetzt können Sie einen Haltepunkt setzen und die rekursive Beschreibung in LLDB ausdrucken:

po view.recursiveDescription() as NSString
8
bernhard

Wenn Sie die Ansichtshierarchie in lldb anzeigen möchten, müssen Sie keine Kategorien oder Überbrückungsheader oder ähnliches hinzufügen. Beim Debuggen von Objective-C-Code würde im Allgemeinen der folgende Befehl an der (lldb)-Eingabeaufforderung verwendet:

po [[UIWindow keyWindow] recursiveDescription]

Wenn Sie jedoch in einem Swift-Frame angehalten haben, kann lldb einen Swift-Ausdruck erwarten. Sie können jedoch expr explizit angeben (die Abkürzung po ruft tatsächlich expression auf), in welcher Sprache sich der Ausdruck befindet:

expr -l objc++ -O -- [[UIWindow keyWindow] recursiveDescription]

Die gleichen Muster treten in iOS 8 auf, wenn Sie die View Controller-Hierarchie anzeigen.

po [UIViewController _printHierarchy]

oder im schnellen Rahmen:

expr -l objc++ -O -- [UIViewController _printHierarchy]

In WWDC 2018 Advanced Debugging with Xcode schlagen sie vor, sich von dieser komplizierten expr-Syntax zu lösen, indem sie einen Alias ​​poc definieren, indem sie eine Textdatei ~/.lldbinit mit der folgenden Zeile erstellen:

command alias poc expression -l objc -O --

Dann kannst du Dinge tun wie:

poc [UIViewController _printHierarchy]

Es ist erwähnenswert, dass Xcode 8 den View Debugger eingeführt hat (klicken Sie auf  view debug button ) bietet eine interaktivere Methode zum Analysieren der Ansichtshierarchie, wodurch die LLDB-Variable recursiveDescription der Ansichtshierarchie weitgehend entfällt. Weitere Informationen finden Sie unter WWDC 2016 video Visual Debugging mit Xcode . Zugegebenermaßen müssen wir manchmal auf die oben gezeigte recursiveDescription-Technik zurückgreifen, aber meistens macht der View-Debugger diesen Prozess viel natürlicher und intuitiver.

In Xcode 9 wurde der View-Debugger erweitert, sodass jetzt auch die entsprechenden View-Controller enthalten sind:

 enter image description here

80
Rob

In Swift 2.0 können Sie einfach ausführen:

po view.performSelector("recursiveDescription")

In (getestet mit iOS10 Beta3) Swift 3.0 ist dies etwas komplexer:

po let s = view.perform("recursiveDescription"); print(s)

64
Ron
po view.value(forKey: "recursiveDescription")!
16
rob mayoff

Fügen Sie zunächst eine Kategorie @interface ohne @implementation in Ihrem Bridging-Header hinzu.

@interface UIView (Debug)
- (id)recursiveDescription;
- (id)_autolayoutTrace;  // This one is even sweeter
@end

dann in deiner Konsole

po self.recursiveDescription() as NSString
po self._autolayoutTrace() as NSString

Der Schlüssel hier ist as NSString nicht as String

7
CopperCash
expression -l objc -O -- [`self.view` recursiveDescription]

Es ist erforderlich, es im Objective-C-Format einzugeben, da UIKit im Objective-C-Framework ist.

Rekursive Beschreibung existiert nur zu Debugging-Zwecken. Es ist nicht Teil der öffentlichen API und daher für Swift nicht verfügbar

Und Swift ist eine strikte Sprache und erlaubt nicht das Aufrufen von Funktionen, die nicht genau definiert wurden.

Objective-C ist eine dynamische Sprache, mit der Sie Funktionen wie diese aufrufen können.

Wir müssen also dem Debugger mitteilen, dass er diesen Ausdruck in einer Objective-C-Syntax auswerten soll

Und das tun Sie, wenn Sie expression mit der Option - l objc verwenden

-O, sagen Sie dem Debugger, dass wir die Debug-Beschreibung genauso wünschen wie po und - um anzuzeigen, dass es keine weiteren Optionen gibt.

Wir müssen die [self.view] -Ansicht in hintere Ticks setzen.

[`self.view`]

Back Ticks ist wie ein Vorprozessschritt, in dem zuerst der Inhalt des aktuellen Frames ausgewertet und das Ergebnis eingefügt wird. Anschließend können wir den Rest auswerten.

Meine Antwort stammt von WWDC 2018 Session 412 für fortgeschrittenes Debuggen mit Xcode und lldb.

3
ManuelMB

Fügen Sie dem Bridging-Header eine Deklaration einer UIView-Kategorie mit dieser Methode hinzu.

1
newacct

Aufbauend auf @Rob MayoffsAntwort :

extension UIView {

   /**
    Wrapper for useful debugging description of view hierarchy
   */
   var recursiveDescription: NSString {
       return value(forKey: "recursiveDescription") as! NSString
   }

}
0