Есть ли способ получить ВСЕ представления, подпредставления и подпредставления этих подпредставлений (вы поняли ...) NSWindow?
Спасибо.
Есть ли способ получить ВСЕ представления, подпредставления и подпредставления этих подпредставлений (вы поняли ...) NSWindow?
Спасибо.
Вот категория в NSView:
@interface NSView (MDRecursiveSubviews)
- (NSArray *)allSubviews;
@end
@implementation NSView (MDRecursiveSubviews)
- (NSArray *)allSubviews {
NSMutableArray *allSubviews = [NSMutableArray arrayWithObject:self];
NSArray *subviews = [self subviews];
for (NSView *view in subviews) {
[allSubviews addObjectsFromArray:[view allSubviews]];
}
return [[allSubviews copy] autorelease];
}
@end
С помощью быстрого файла с перьями, который я создал с иерархией представлений, он напечатал следующее:
[RecursiveSubviewsAppDelegate awakeFromNib] allSubviews == (
"<NSView: 0x10390dfd0>",
"<NSView: 0x103c07ae0>",
"<NSView: 0x100129cc0>",
"<NSButton: 0x100115ce0>",
"<NSButton: 0x100116900>",
"<NSButton: 0x1001165c0>",
"<NSButton: 0x100116130>",
"<NSButton: 0x100114ad0>",
"<NSButton: 0x100115910>",
"<NSButton: 0x100115090>",
"<NSScrollView: 0x103b07a30>",
"<NSClipView: 0x103b07d40>",
"<NSTextView: 0x103b083c0>\n
Frame = {{0.00, 0.00}, {159.00, 58.00}},
Bounds = {{0.00, 0.00}, {159.00, 58.00}}\n
Horizontally resizable: NO, Vertically resizable: YES\n
MinSize = {159.00, 58.00}, MaxSize = {463.00, 10000000.00}\n",
"<NSScroller: 0x1001145b0>",
"<NSScroller: 0x100114840>",
"<NSScrollView: 0x10390ea00>",
"<NSClipView: 0x10390ef10>",
"<NSTableView: 0x10390f570>",
"<NSScroller: 0x103b06f10>",
"<NSScroller: 0x103b07460>",
"<NSClipView: 0x1039105d0>",
"<NSTableHeaderView: 0x103910300>",
"<_NSCornerView: 0x103911c20>"
Одно замечание, вызывающее беспокойство, которое я должен добавить, заключается в том, что мне неясно, как это может быть полезно, кроме как в качестве инструмента отладки. Но даже тогда, вероятно, есть более простые способы сделать что-то.
Есть личное сообщение, которое можно отправить на NSView
, чтобы распечатать иерархию управления.
[NSView _subtreeDescription]
дает вам всю иерархию NSView
, то есть его дочерние элементы и их дочерние элементы.
Если я вас правильно понял, вам придется создать метод, который рекурсивно вызывает сам себя. Что-то вроде этого:
- (NSArray *)allSubviewsOfView:(NSView *)view
{
NSMutableArray *subviews = [[view subviews] mutableCopy];
for (NSView *subview in [view subviews])
[subviews addObjectsFromArray:[self allSubviewsOfView:subview]]; //recursive
return subviews;
}
Затем вы бы назвали что-то вроде
NSArray *allSubviewsOfWindow = [self allSubviewsOfView:[window contentView]];
чтобы узнать ваше мнение. (И не забывайте управлять памятью, если вы не используете сборщик мусора.)
contentView
окна.
- person Peter Hosey; 27.03.2011
return
(или аналогичного оператора управления), метод будет рекурсивно повторяться бесконечно.
- person Moshe; 27.03.2011
subviews
? Он работает и встроен в SDK.
- person Moshe; 27.03.2011
NSButton
- когда он вызывает этот метод, [self subviews]
будет пустым массивом, в который не будет повторяться рекурсия, и позволит оператору for/in
перейти к следующему элементу.
- person NSGod; 27.03.2011
collectedViews
, чтобы избежать путаницы.
- person Rob van der Veer; 28.07.2013
Не уверен в бесконечной рекурсии в других ответах, но вы определенно не можете изменить массив, пока вы выполняете быстрое перечисление. Вот метод, который я написал для iOS, который выполняет итерацию по всем подпредставлениям до тех пор, пока не останется больше для изучения. Я предполагаю, что то же самое или подобное подойдет для NSView. Надеюсь это поможет.
(Изменить: сейчас ... если бы я просто посмотрел немного дальше в своих результатах поиска, я бы нашел этот действительно простой способ сначала сделать это: Как я могу в цикле перебрать все подпредставления UIView, а также их подпредставления и их подпредставления а>)
- (NSMutableArray *)allSubviewsInView:(UIView *)parentView {
NSMutableArray *allSubviews = [[NSMutableArray alloc] initWithObjects: nil];
NSMutableArray *currentSubviews = [[NSMutableArray alloc] initWithObjects: parentView, nil];
NSMutableArray *newSubviews = [[NSMutableArray alloc] initWithObjects: parentView, nil];
while (newSubviews.count) {
[newSubviews removeAllObjects];
for (UIView *view in currentSubviews) {
for (UIView *subview in view.subviews) [newSubviews addObject:subview];
}
[currentSubviews removeAllObjects];
[currentSubviews addObjectsFromArray:newSubviews];
[allSubviews addObjectsFromArray:newSubviews];
}
NSLog(@"\n%d total subviews:\n%@",allSubviews.count, allSubviews);
return allSubviews;
}
Зарегистрированные результаты из образца просмотра:
18 total subviews:
(
"<UIRoundedRectButton: 0x6a7a590; frame = (26 20; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6a772d0>>",
"<UISwitch: 0x6a7f930; frame = (26 76; 79 27); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6a7fa20>>",
"<UIImageView: 0x685e4a0; frame = (82 20; 139 139); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x685eca0>>",
"<UITextView: 0x6893e40; frame = (20 196; 192 79); text = 'Lorem ipsum dolor sit er ...'; clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x687c330>; contentOffset: {0, 0}>",
"<UIView: 0x6a88af0; frame = (26 304; 198 123); autoresize = RM+BM; tag = 1; layer = <CALayer: 0x6a88b20>>",
"<UIButtonLabel: 0x6a7f410; frame = (0 0; 0 0); clipsToBounds = YES; hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6a7f4d0>>",
"<_UISwitchInternalView: 0x6a7fa50; frame = (-1 0; 79 27); layer = <CALayer: 0x6a79b90>>",
"<UITextSelectionView: 0x6894070; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x68940d0>>",
"<UIImageView: 0x68924b0; frame = (0 72; 192 7); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x6892520>>",
"<UIImageView: 0x6894100; frame = (185 0; 7 79); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x6894180>>",
"<UIWebDocumentView: 0x7416600; frame = (0 0; 192 394); text = 'Lorem ipsum dolor sit er ...'; opaque = NO; userInteractionEnabled = NO; layer = <UIWebLayer: 0x6895330>>",
"<UIView: 0x6a88b50; frame = (10 10; 80 80); autoresize = W+H; tag = 2; layer = <CALayer: 0x6a88b80>>",
"<UIImageView: 0x6a80610; frame = (1 0; 77 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6a80650>>",
"<UIView: 0x6a806f0; frame = (1 0; 77 27); clipsToBounds = YES; alpha = 0; layer = <CALayer: 0x6a80720>>",
"<UIView: 0x6a88fa0; frame = (5 5; 50 50); autoresize = W+H; tag = 3; layer = <CALayer: 0x6a88fd0>>",
"<UIImageView: 0x6a808e0; frame = (-2 0; 79 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6a84d30>>",
"<UIImageView: 0x6a84c00; frame = (-2 0; 131 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6a84d90>>",
"<UIImageView: 0x6a84c40; frame = (49 0; 29 27); userInteractionEnabled = NO; layer = <CALayer: 0x6a84c80>>"
)
Вышеупомянутое решение не будет работать, если в представлениях есть представления. Нам потребуется рекурсивное решение, как показано ниже.
-(void) printViewHierarchy: (UIView * ) view withTag: (NSInteger) tag {
if (view == nil) {
return;
}
if (view == nil || [view tag] == tag) {
NSLog(@"%@", view);
return;
}
for (UIView * subview in [view subviews]) {
[self printViewHierarchy: subview withTag: tag];
}
}
- (void) findAllViews {
UIView * baseView = [UIView new];
[baseView setTag: 1];
UIView * secondRowA = [UIView new];
[secondRowA setTag: 2];
UIView * secondRowB = [UIView new];
[secondRowB setTag: 3];
UIView * thirdRowA = [UIView new];
[thirdRowA setTag: 4];
UIView * thirdRowB = [UIView new];
[thirdRowB setTag: 5];
[secondRowA addSubview: thirdRowA];
[secondRowB addSubview: thirdRowB];
[baseView addSubview: secondRowA];
[baseView addSubview: secondRowB];
[self printViewHierarchy: baseView withTag: 6];
}