2011-03-27 57 views
12

有沒有一種方法可以獲得NSWindow的所有視圖和子視圖以及這些子視圖的子視圖(您明白...)?獲取NSWindow的所有視圖和子視圖

謝謝。

+3

歡迎的StackOverflow!爲什麼不把用戶名從user635064更改爲更獨特的東西?此外,如果您標記正確答案,您將更有可能獲得幫助。 – Moshe 2011-03-27 03:08:00

+2

同意關於用戶名,但不知道爲什麼你告訴我關於標記問題是否正確?我總是標記一個正確的問題,如果它幫助我... – user635064 2011-03-27 03:29:52

+0

@用戶彼得是正確的。 – Moshe 2011-03-27 04:42:50

回答

9

這裏是一個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>" 

一個問題的筆記我要補充的是,這是我不清楚如何做到這一點是有用的,但作爲調試工具。但即使如此,可能還有更簡單的做事方式。

+0

適用於iOS:NS - > UI。 – clozach 2012-08-28 16:24:46

3

如果我正確理解了你,你將不得不創建一個遞歸調用自己的方法。事情是這樣的:

- (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做內存管理。)

+0

遞歸方法將永遠不會像您設計的那樣結束。 – Moshe 2011-03-27 03:10:11

+0

謝謝,雖然這將無限地遞歸,直到堆棧溢出,我會添加一個基本情況。但這是最好的方式嗎? – user635064 2011-03-27 03:32:23

+1

@Enchilada:不要忘記釋放陣列。 @ user635064:不,它不會無限遞歸。如果你添加了一個視圖作爲它自己的子視圖的子視圖,那麼它可能是一個閉環,不能從窗口的'contentView'到達。 – 2011-03-27 03:41:45

2

不確定其他答案中的無限遞歸,但是當您在其上進行快速枚舉時絕對不能修改數組。下面是我爲iOS編寫的一個方法,它遍歷所有子視圖,直到沒有更多的東西需要探索。我認爲相同或相似的工作對於NSView。希望這可以幫助。

(編輯:現在......如果我剛剛看了一點點進一步下跌我的搜索結果,我早就發現了這個非常簡單的方法,首先做到這一點:How can I loop through all subviews of a UIView, and their subviews and their subviews

- (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>>" 
) 
-2
NSArray *arrofView = [[self view] subviews]; 
+0

該OP正在尋找子視圖_and_他們的子視圖(等等,我想)。 – Monolo 2012-07-13 20:59:06

8

有可以在NSView被髮送到打印控制層次悄悄話。

[NSView _subtreeDescription]爲您提供了NSView(即其子女及其子女)的整個層次結構。

4
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); 
    ... 
0

如果視圖內有視圖,上述解決方案將不起作用。我們需要做一個遞歸解決方案,如下所示。

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