Objective c 获取NSWindow的所有视图和子视图

Objective c 获取NSWindow的所有视图和子视图,objective-c,cocoa,nsview,nswindow,Objective C,Cocoa,Nsview,Nswindow,是否有一种方法可以获取NSWindow的所有视图和子视图以及这些子视图的子视图(您知道了…) 谢谢。如果我理解正确,您必须创建一个递归调用自身的方法。大概是这样的: - (NSArray *)allSubviewsOfView:(NSView *)view { NSMutableArray *subviews = [[view subviews] mutableCopy]; for (NSView *subview in [view subviews]) [subviews ad

是否有一种方法可以获取NSWindow的所有视图和子视图以及这些子视图的子视图(您知道了…)


谢谢。

如果我理解正确,您必须创建一个递归调用自身的方法。大概是这样的:

- (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,请不要忘记进行内存管理。)

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>"
[RecursiveSubviewsAppDelegate awakeFromNib]所有子视图==(
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
“\n
帧={0.00,0.00},{159.00,58.00},
界限={0.00,0.00},{159.00,58.00}\n
水平可调整大小:否,垂直可调整大小:是\n
MinSize={159.00,58.00},MaxSize={463.00,10000000.00}\n“,
"",
"",
"",
"",
"",
"",
"",
"",
"",
""

我需要补充的一点是,除了作为调试工具外,我不清楚这将如何发挥作用。但即便如此,可能还有更简单的方法来做事情。

在其他答案中不确定无限递归,但在对数组进行快速枚举时,您肯定不能修改数组。下面是我编写的一个方法te for iOS,迭代所有子视图,直到没有更多的子视图可供探索。我认为相同或类似的方法适用于NSView。希望这能有所帮助

(编辑:现在……如果我只是在我的搜索结果中再往下看一点,我会首先找到一个非常简单的方法:)

从示例视图记录的结果:

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>>"
)
18个总子视图:
(
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
)

有一条私人消息可以在
NSView
上发送以打印控制层次结构

[NSView\u subtreeDescription]
提供了
NSView
的整个层次结构,即其子级及其子级。

静态无效转储视图(NSView*v,int级别){
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);
    ...
NSString*缩进=@; 对于(int i=0;i
如果视图中存在视图,则上述解决方案将不起作用。我们需要执行如下所示的递归解决方案

-(void)printViewHierarchy:(UIView*)带标记的视图:(NSInteger)标记{
如果(视图==nil){
返回;
}
如果(视图==nil | |[视图标记]==tag){
NSLog(@“%@”,视图);
返回;
}
对于(UIView*子视图在[视图子视图]中){
[自打印视图层次结构:带标记的子视图:标记];
}
}
-(无效)FindallView{
UIView*baseView=[UIView新建];
[baseView设置标签:1];
UIView*secondRowA=[UIView new];
[secondRowA setTag:2];
UIView*secondRowB=[UIView新建];
[secondRowB设置标签:3];
UIView*thirdRowA=[UIView新建];
[thirdRowA setTag:4];
UIView*thirdRowB=[UIView new];
[thirdRowB setTag:5];
[secondRowA addSubview:thirdRowA];
[secondRowB addSubview:thirdRowB];
[baseView addSubview:secondRowA];
[baseView addSubview:secondRowB];
[自打印视图层次结构:带标签的baseView:6];

}
欢迎使用StackOverflow!为什么不将您的用户名从user635064更改为更独特的名称?此外,如果您标记正确的答案,您将更有可能获得帮助。同意用户名,但不知道您为什么要告诉我将问题标记为正确?如果问题对我有帮助,我总是将问题标记为正确…只需添加您的v查看NSMutableArray以供稍后枚举。递归方法永远不会像您设计的那样结束。谢谢,虽然这将无限递归直到堆栈溢出,但我将添加一个基本大小写。但这是最好的方法吗?@Enchilada:别忘了释放数组。@user635064:不,它不会无限递归。如果您将视图添加为subv,它可能会无限递归查看它自己的一个子视图,但这将是一个封闭的循环,无法从窗口的
contentView
@Enchilada:此方法的真正问题不是它无限递归,而是您正在枚举一个正在变异的数组。呸,无法编辑我以前的注释。这里有一个更好的:@Moshe:它只会递归一个数组因此,除非您可以创建nib文件或以编程方式创建具有无限多个子视图的视图层次结构(其行为将导致“第一个”无限递归,而不是调用该方法时遇到的任何递归),否则没有无限递归。OP正在查找子视图及其子视图(我猜是等)。也适用于iOS:NS->UI。不适用于ARC:**-[NSMutableArray addObjectsFromArray:::]:数组参数不是NSArray“更简单的操作方式”只需将视图添加到NSMutableArray,并在更大的范围内访问该NSMutableArray,这样做的效率也要高得多。
NSArray *arrofView = [[self view] subviews];
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);
    ...