pantalla descargar color cambio apple iphone objective-c loops uiview subview

descargar - iphone 7



¿Cómo puedo recorrer todas las subvistas de una UIView y sus subvistas y sus subvistas? (18)

Acabo de encontrar una forma interesante de hacerlo a través del depurador:

http://idevrecipes.com/2011/02/10/exploring-iphone-view-hierarchies/

hace referencia a esta técnica de Apple:

https://developer.apple.com/library/content/technotes/tn2239/_index.html#SECUIKIT

Solo asegúrese de que su depurador esté en pausa (establezca un punto de interrupción de pausa manualmente) y puede solicitar la recursiveDescription .

¿Cómo puedo recorrer todas las subvistas de una UIView, y sus subvistas y sus subvistas?


Aquí hay otra implementación de Swift:

extension UIView { var allSubviews: [UIView] { return self.subviews.flatMap { [$0] + $0.allSubviews } } }


Aquí hay un código recursivo:

for (UIView *subViews in yourView.subviews) { [self removSubviews:subViews]; } -(void)removSubviews:(UIView *)subView { if (subView.subviews.count>0) { for (UIView *subViews in subView.subviews) { [self removSubviews:subViews]; } } else { NSLog(@"%i",subView.subviews.count); [subView removeFromSuperview]; } }


Aquí hay un ejemplo con la funcionalidad real de bucle y corte de vista.

typedef void(^ViewBlock)(UIView* view, BOOL* stop); @interface UIView (ViewExtensions) -(void) loopViewHierarchy:(ViewBlock) block; @end @implementation UIView (ViewExtensions) -(void) loopViewHierarchy:(ViewBlock) block { BOOL stop = NO; if (block) { block(self, &stop); } if (!stop) { for (UIView* subview in self.subviews) { [subview loopViewHierarchy:block]; } } } @end

Ejemplo de llamada:

[mainView loopViewHierarchy:^(UIView* view, BOOL* stop) { if ([view isKindOfClass:[UIButton class]]) { /// use the view *stop = YES; } }];


Aquí hay una variación de la respuesta anterior de Ole Begemann , que agrega una sangría para ilustrar la jerarquía:

// UIView+HierarchyLogging.h @interface UIView (ViewHierarchyLogging) - (void)logViewHierarchy:(NSString *)whiteSpaces; @end // UIView+HierarchyLogging.m @implementation UIView (ViewHierarchyLogging) - (void)logViewHierarchy:(NSString *)whiteSpaces { if (whiteSpaces == nil) { whiteSpaces = [NSString string]; } NSLog(@"%@%@", whiteSpaces, self); NSString *adjustedWhiteSpaces = [whiteSpaces stringByAppendingFormat:@" "]; for (UIView *subview in self.subviews) { [subview logViewHierarchy:adjustedWhiteSpaces]; } } @end


Bueno, aquí está mi solución usando recursion y un contenedor (categoría / extensión) para la clase UIView.

// UIView+viewRecursion.h @interface UIView (viewRecursion) - (NSMutableArray*) allSubViews; @end // UIView+viewRecursion.m @implementation UIView (viewRecursion) - (NSMutableArray*)allSubViews { NSMutableArray *arr=[[[NSMutableArray alloc] init] autorelease]; [arr addObject:self]; for (UIView *subview in self.subviews) { [arr addObjectsFromArray:(NSArray*)[subview allSubViews]]; } return arr; } @end

Uso: Ahora debería recorrer todas las vistas secundarias y manipularlas según sea necesario.

//disable all text fields for(UIView *v in [self.view allSubViews]) { if([v isKindOfClass:[UITextField class]]) { ((UITextField*)v).enabled=NO; } }


Con la ayuda de Ole Begemann. Agregué algunas líneas para incorporar el concepto de bloque en él.

UIView + HierarchyLogging.h

typedef void (^ViewActionBlock_t)(UIView *); @interface UIView (UIView_HierarchyLogging) - (void)logViewHierarchy: (ViewActionBlock_t)viewAction; @end

UIView + HierarchyLogging.m

@implementation UIView (UIView_HierarchyLogging) - (void)logViewHierarchy: (ViewActionBlock_t)viewAction { //view action block - freedom to the caller viewAction(self); for (UIView *subview in self.subviews) { [subview logViewHierarchy:viewAction]; } } @end

Usando la categoría HierarchyLogging en su ViewController. Ahora tiene libertad para lo que necesita hacer.

void (^ViewActionBlock)(UIView *) = ^(UIView *view) { if ([view isKindOfClass:[UIButton class]]) { NSLog(@"%@", view); } }; [self.view logViewHierarchy: ViewActionBlock];


Creo que todas las respuestas que usan recursividad (excepto la opción del depurador) utilizan categorías. Si no necesita / desea una categoría, puede usar un método de instancia. Por ejemplo, si necesita obtener una matriz de todas las etiquetas en su jerarquía de vistas, puede hacerlo.

@interface MyViewController () @property (nonatomic, retain) NSMutableArray* labelsArray; @end @implementation MyViewController - (void)recursiveFindLabelsInView:(UIView*)inView { for (UIView *view in inView.subviews) { if([view isKindOfClass:[UILabel class]]) [self.labelsArray addObject: view]; else [self recursiveFindLabelsInView:view]; } } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.labelsArray = [[NSMutableArray alloc] init]; [self recursiveFindLabelsInView:self.view]; for (UILabel *lbl in self.labelsArray) { //Do something with labels } }


Desearía haber encontrado esta página primero, pero si (por alguna razón) quieres hacer esto de forma no recursiva, no en una Categoría y con más líneas de código


El código publicado en esta respuesta atraviesa todas las ventanas y todas las vistas y todas sus subvistas. Se usó para volcar una impresión de la jerarquía de vistas en NSLog, pero puede usarla como base para cualquier cruce de la jerarquía de vistas. Utiliza una función C recursiva para recorrer el árbol de vista.


El siguiente método crea una o más matrices mutables, luego realiza un bucle a través de las subvistas de la vista de entrada. Al hacerlo, agrega la subvista inicial luego consultas sobre si hay subvistas de esa subvista. Si es verdadero, se llama de nuevo. Lo hace hasta que se hayan agregado todas las vistas de la jerarquía.

-(NSArray *)allSubs:(UIView *)view { NSMutableArray * ma = [NSMutableArray new]; for (UIView * sub in view.subviews){ [ma addObject:sub]; if (sub.subviews){ [ma addObjectsFromArray:[self allSubs:sub]]; } } return ma; }

Llamar usando:

NSArray * subviews = [self allSubs:someView];


Escribí una categoría hace algún tiempo para depurar algunas vistas.

IIRC, el código publicado es el que funcionó. Si no, te señalará en la dirección correcta. Usar bajo su propio riesgo, etc.


Esto muestra el nivel de jerarquía también

@implementation UIView (ViewHierarchyLogging) - (void)logViewHierarchy:(int)level { NSLog(@"%d - %@", level, self); for (UIView *subview in self.subviews) { [subview logViewHierarchy:(level+1)]; } } @end


Lo etiqueto todo cuando es creado. Entonces es fácil encontrar cualquier subvista.

view = [aView viewWithTag:tag];


No es necesario crear ninguna función nueva. Solo hazlo cuando estés depurando con Xcode.

Establezca un punto de interrupción en un controlador de vista y haga que la aplicación se detenga en este punto de interrupción.

Haga clic con el botón derecho en el área vacía y presione "Agregar expresión ..." en la ventana de observación de Xcode.

Ingrese esta línea:

(NSString*)[self->_view recursiveDescription]

Si el valor es demasiado largo, haga clic con el botón derecho y seleccione "Imprimir descripción de ...". Verá todas las subvistas de self.view en la ventana de la consola. Cambie self -> _ view a algo más si no quiere ver las subvistas de self.view.

¡Hecho! ¡No gdb!


Por cierto, hice un proyecto de código abierto para ayudar con este tipo de tarea. Es realmente fácil y usa bloques Objective-C 2.0 para ejecutar código en todas las vistas en una jerarquía.

https://github.com/egold/UIViewRecursion

Ejemplo:

-(void)makeAllSubviewsGreen { [self.view runBlockOnAllSubviews:^(UIView *view) { view.backgroundColor = [UIColor greenColor]; }]; }


Una solución en Swift 3 que ofrece todas las subviews sin incluir la vista en sí:

extension UIView { var allSubViews : [UIView] { var array = [self.subviews].flatMap {$0} array.forEach { array.append(contentsOf: $0.allSubViews) } return array } }


Use recursión:

// UIView+HierarchyLogging.h @interface UIView (ViewHierarchyLogging) - (void)logViewHierarchy; @end // UIView+HierarchyLogging.m @implementation UIView (ViewHierarchyLogging) - (void)logViewHierarchy { NSLog(@"%@", self); for (UIView *subview in self.subviews) { [subview logViewHierarchy]; } } @end // In your implementation [myView logViewHierarchy];