Как я могу перебирать все подпункты UIView, а также их подзоны и их подпрограммы

Как я могу перебирать все подпрограммы UIView, их подвид и их подвид?

Использовать рекурсию:

// 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]; 

Ну вот мое решение, используя рекурсию и оболочку (категорию / расширение) для classа 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 

Использование: теперь вам нужно перебирать все подпункты и манипулировать ими по мере необходимости.

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

Решение в Swift 3, которое дает все subviews без включения самого представления:

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

Просто нашел интересный способ сделать это через отладчик:

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

ссылается на это Apple Technote:

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

Просто убедитесь, что ваш отладчик приостановлен (либо установите точку прерывания, чтобы приостановить его вручную), и вы можете запросить recursiveDescription .

Я отмечаю все, когда он создан. Тогда легко найти любое подзапрос.

 view = [aView viewWithTag:tag]; 

С помощью Оле Бегеманна. Я добавил несколько строк, чтобы включить концепцию блока в нее.

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 

Использование категории HierarchyLogging в вашем ViewController. Теперь у вас есть свобода в том, что вам нужно делать.

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

Вот рекурсивный код: –

  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]; } } 

Кстати, я сделал проект с открытым исходным кодом, чтобы помочь в решении такого рода задач. Это очень просто и использует блоки Objective-C 2.0 для выполнения кода во всех представлениях в иерархии.

https://github.com/egold/UIViewRecursion

Пример:

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

Не нужно создавать никаких новых функций. Просто делайте это при отладке с помощью Xcode.

Установите контрольную точку в controllerе просмотра и сделайте паузу приложения в этой точке останова.

Щелкните правой кнопкой мыши пустую область и нажмите «Добавить выражение …» в окне просмотра Xcode.

Введите эту строку:

 (NSString*)[self->_view recursiveDescription] 

Если значение слишком велико, щелкните его правой кнопкой мыши и выберите «Печать описания …». В окне консоли вы увидите все subviews self.view. Измените self -> _ view на что-то еще, если вы не хотите видеть subviews self.view.

Готово! Нет gdb!

Вот пример с фактической реализацией цикла просмотра и разбиения.

 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 

Пример вызова:

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

Ниже приведен вариант ответа Оле Бегемана , который добавляет отступы для иллюстрации иерархии:

 // 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 

Код, размещенный в этом ответе, проходит через все windows и все представления и все их дочерние объекты. Он использовался для сброса распечатки иерархии представлений в NSLog, но вы можете использовать ее в качестве основы для любого обхода иерархии представлений. Он использует рекурсивную функцию C, чтобы пересечь дерево представлений.

Некоторое время назад я написал категорию, чтобы отлаживать некоторые виды.

IIRC, опубликованный код – тот, который работал. Если нет, он укажет вам в правильном направлении. Использовать на свой страх и риск.

Это также отображает уровень иерархии

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

Хотелось бы, чтобы я сначала нашел эту страницу , но если (по какой-то причине) вы хотите сделать это нерекурсивно, а не в категории, и с большим количеством строк кода

Я думаю, что все ответы, использующие рекурсию (за исключением опции отладчика), используют категории. Если вам не нужна / нужна категория, вы можете просто использовать метод экземпляра. Например, если вам нужно получить массив всех меток в иерархии представлений, вы можете это сделать.

 @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 } } 

Вот еще одна реализация Swift:

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

В приведенном ниже методе создается один или несколько изменяемых массивов, а затем проходит через подзоны входного представления. При этом он добавляет начальное подчинение, а затем запросы относительно того, есть ли какие-либо подзадачи этого подвью. Если это правда, он снова называет себя. Он делает это до тех пор, пока не будут добавлены все представления иерархии.

 -(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; } 

Позвоните, используя:

 NSArray * subviews = [self allSubs:someView]; 
  • Как создать цикл ViewPager?
  • Создание треугольника с петлями
  • Как сгенерировать разные случайные числа в цикле в C ++?
  • Каков наилучший способ перебора словаря?
  • Однострочный цикл с обязательной парой фигурных скобок в Java
  • Когда это делать?
  • Печать * s как треугольники в Java?
  • Почему memcpy () и memmove () быстрее, чем указатели?
  • Страница непрерывной петли (не бесконечный свиток)
  • Фоновый цикл Python при запуске других команд
  • Отображать номера от 1 до 100 без петель или условий
  • Давайте будем гением компьютера.