Есть ли способ, которым я могу получить ВСЕ представления и подзаголовки и подзаголовки этих подзонов (вы получите идею...) 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
С быстрым файлом nib, который я создал с иерархией представлений, он напечатал это:
[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
, то есть ее детей и их детей.
static void dumpViews(NSView* v, int level) {
NSString* indent = @"";
for (int i = 0; i < level; i++) {
indent = [indent stringByAppendingString:@" "];
}
NSLog(@"%@%@ %@", indent, [v class], NSStringFromRect(v.frame));
if (v.subviews != null) {
for (id s in v.subviews) {
dumpViews(s, level + 1);
}
}
}
- (void) windowControllerDidLoadNib: (NSWindowController*) controller {
NSWindow* window = controller.window;
dumpViews(window.contentView, 0);
...
Если вы правильно поняли, вам нужно будет создать метод, который вызывает себя рекурсивно. Что-то вроде этого:
- (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]];
чтобы получить ваши мнения. (И не забудьте сделать управление памятью, если вы не используете GC.)
Не уверен в бесконечной рекурсии в других ответах, но вы определенно не можете изменять массив, пока вы делаете быстрое перечисление на нем. Здесь метод, который я написал для iOS, который выполняет итерации через все подпункты, пока их больше не осталось исследовать. Я предполагаю, что для NSView будет работать то же самое или подобное. Надеюсь, это поможет.
(Edit: now... если бы я только немного посмотрел на мои результаты поиска, я бы нашел это очень простой способ сделать это сначала: Как я могу пропустить все subviews 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];
}
NSArray *arrofView = [[self view] subviews];