ios - navigationitem title color
Método de descripción recursiva en Swift? (8)
¿Hay una manera de usar [self.view recursiveDescription] en Swift? Estoy intentando usar este método pero obtengo el siguiente error:
''UIView'' does not have a member named ''recursiveDescription''
¿Alguna sugerencia?
Agregue al encabezado de puente una declaración de una categoría de UIView con ese método.
En Swift 2.0 puedes simplemente ejecutar:
@interface UIView (Debug)
- (id)recursiveDescription;
- (id)_autolayoutTrace; // This one is even sweeter
@end
En (probado con iOS10 Beta3) swift 3.0 esto es un poco más complejo:
po let s = view.perform("recursiveDescription"); print(s)
Para acceder a la API privada / no documentada de Objective-C (como el método UIView
en UIView
) desde Swift, puede hacer lo siguiente:
- Cree una nueva categoría de Objective-C en la clase en la que se define el método privado (por ejemplo,
UIView
). - Haga clic en Sí si Xcode le pregunta acerca de la configuración de un encabezado de puente. (Si ya tiene un encabezado puente en su proyecto, este paso se omitirá).
- El archivo de implementación (.m) de la categoría puede ser eliminado.
Declara el método privado en el encabezado de la categoría:
// UIView+Debugging.h @interface UIView (Debugging) - (id)recursiveDescription; @end
Ahora puede establecer un punto de interrupción e imprimir la descripción recursiva en LLDB:
po view.recursiveDescription() as NSString
Primero agregue una categoría @interface
sin @interface
en su encabezado puente.
expression -l objc -O -- [`self.view` recursiveDescription]
entonces en tu consola
[`self.view`]
La clave aquí es as NSString
no as String
Si desea mostrar la jerarquía de vistas en lldb, no tiene que agregar categorías ni encabezados de puente ni nada de eso. Al depurar el código de Objective-C, uno usaría generalmente el siguiente comando en el (lldb)
:
po [[UIWindow keyWindow] recursiveDescription]
Sin embargo, si se ha detenido en un marco Swift, lldb puede esperar una expresión Swift. Sin embargo, puede decirle explícitamente a expr
(la abreviatura de la letra en realidad está llamando a expression
) en qué idioma se encuentra la expresión:
expr -l objc++ -O -- [[UIWindow keyWindow] recursiveDescription]
Los mismos patrones ocurren en iOS 8, al ver la jerarquía del controlador de vista, usando:
po [UIViewController _printHierarchy]
o, en el marco Swift:
expr -l objc++ -O -- [UIViewController _printHierarchy]
En la depuración avanzada de WWDC 2018 con Xcode , sugieren alejarse de esta complicada sintaxis expr
mediante la definición de un alias, poc
, mediante la creación de un archivo de texto, ~/.lldbinit
con la siguiente línea:
po view.performSelector("recursiveDescription")
Entonces puedes hacer cosas como:
po view.value(forKey: "recursiveDescription")!
Vale la pena señalar que Xcode 8 introdujo el depurador de vista (haga clic en ), que ofrece una forma más interactiva de analizar la jerarquía de vistas, eliminando en gran medida la necesidad de la descripción recursiveDescription
LLDB de la jerarquía de vistas. Para más información, vea WWDC 2016 video Visual Debugging with Xcode . Es cierto que a veces terminamos recurriendo a la técnica de recursiveDescription
que se muestra arriba, pero la mayoría de las veces el depurador de vistas hace que este proceso sea mucho más natural e intuitivo.
Y en Xcode 9, han expandido este depurador de vista, por lo que ahora también incluye los controladores de vista relevantes:
Sobre la answer :
extension UIView { /** Wrapper for useful debugging description of view hierarchy */ var recursiveDescription: NSString { return value(forKey: "recursiveDescription") as! NSString } }
extension UIView {
/**
Wrapper for useful debugging description of view hierarchy
*/
var recursiveDescription: NSString {
return value(forKey: "recursiveDescription") as! NSString
}
}
Es necesario ingresarlo en el formato Objective-C porque UIKit está en el marco Objective-C.
La descripción recursiva solo existe para propósitos de depuración. No es parte de la API pública y, por lo tanto, no está disponible para Swift.
Y Swift es un lenguaje estricto y no te permite llamar a funciones que no han sido definidas estrictamente.
Objective-C, es un lenguaje dinámico para que puedas llamar a funciones como esta.
Entonces, lo que debemos hacer es decirle al depurador que evalúe esta expresión en una sintaxis de Objective-C
Y la forma de hacerlo es usar la expresión con la opción - l objc
-O, dígale al depurador que también queremos que la descripción de depuración sea igual a la que haría po y - para indicar que no hay más opciones.
Necesitamos poner la vista [self.view] en las marcas anteriores.
[`self.view`]
Back ticks es como un paso de preproceso que dice primero, evalúa el contenido de esto en el marco actual e inserta el resultado, y luego podemos evaluar el resto.
Mi respuesta se tomó de la depuración avanzada de WWDC 2018 Session 412 con Xcode y lldb.
po self.recursiveDescription() as NSString
po self._autolayoutTrace() as NSString