Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print a control hierarchy in Cocoa?

Tags:

Carbon had a useful function called DebugPrintControlHierarchy.

Is there something similar for NSView or NSWindow?

like image 707
ericg Avatar asked Nov 12 '10 16:11

ericg


3 Answers

I don't know what exactly DebugPrintControlHierarchy printed, but NSView has a useful method call _subtreeDescription which returns a string describing the entire hierarchy beneath the receiver, include classes, frames, and other useful information.

Don't be scared about the leading _ underscore. It's not public API, but it is sanctioned for public use in gdb. You can see it mentioned in the AppKit release notes along with some sample output.

like image 92
kperryua Avatar answered Oct 13 '22 05:10

kperryua


Here's the guts of an NSView category I built awhile back:

+ (NSString *)hierarchicalDescriptionOfView:(NSView *)view 
                                      level:(NSUInteger)level
{

  // Ready the description string for this level
  NSMutableString * builtHierarchicalString = [NSMutableString string];

  // Build the tab string for the current level's indentation
  NSMutableString * tabString = [NSMutableString string];
  for (NSUInteger i = 0; i <= level; i++)
    [tabString appendString:@"\t"];

  // Get the view's title string if it has one
  NSString * titleString = ([view respondsToSelector:@selector(title)]) ? [NSString stringWithFormat:@"%@", [NSString stringWithFormat:@"\"%@\" ", [(NSButton *)view title]]] : @"";

  // Append our own description at this level
  [builtHierarchicalString appendFormat:@"\n%@<%@: %p> %@(%li subviews)", tabString, [view className], view, titleString, [[view subviews] count]];  

  // Recurse for each subview ...
  for (NSView * subview in [view subviews])
    [builtHierarchicalString appendString:[NSView hierarchicalDescriptionOfView:subview 
                                                                          level:(level + 1)]];

  return builtHierarchicalString;
}

- (void)logHierarchy
{
  NSLog(@"%@", [NSView hierarchicalDescriptionOfView:self
                                               level:0]);
}

Usage

Dump this into an NSView category, dump this in it. Include the category header wherever you want to use it, then call [myView logHierarchy]; and watch it go.

like image 32
Joshua Nozzi Avatar answered Oct 13 '22 05:10

Joshua Nozzi


Swift 4.

macOS:

extension NSView {

   // Prints results of internal Apple API method `_subtreeDescription` to console.
   public func dump() {
      Swift.print(perform(Selector(("_subtreeDescription"))))
   }
}

iOS:

extension UIView {

   // Prints results of internal Apple API method `recursiveDescription` to console.
   public func dump() {
      Swift.print(perform(Selector(("recursiveDescription"))))
   }
}

Usage (in debugger): po myView.dump()

like image 36
Vlad Avatar answered Oct 13 '22 04:10

Vlad