views:

405

answers:

2

I occasionally want to change an NSView's dimensions programmaticaly. To do this, it is helpful to get the dimensions of various views, adjust them relative to each other, and then use setFrame: to reposition.

The problem is that the frame method usually returns NSRects that are clearly wrong, from my perspective.

I have a program with an NSPanel set up in Interface Builder and various connections to my main program. To test the NSRects returned by frame, I opened the panel in my application's awakeFromNib: method, retrieved some NSRects, and printed them to the console.

Here is my awakeFromNib:

- (void)awakeFromNib {
  NSLog(@"in awakeFromNib");
  [self showPrefsSheet:self]; //this is the prefs sheet with the controls of interest
                              //note that it does indeed pop up and is displayed
  originalFrame = [aTextView frame];
  NSLog(@"the frame is %d, %d, %d, %d", originalFrame.origin.x, originalFrame.origin.y, originalFrame.size.width, originalFrame.size.height);
  originalFrame = [aButton frame];
  NSLog(@"the frame is %d, %d, %d, %d", originalFrame.origin.x, originalFrame.origin.y, originalFrame.size.width, originalFrame.size.height);
  return;
  }

The results of this code look like this in the console:

in awakeFromNib
the frame is 0, 0, 0, 0
the frame is 0, 1079230464, 0, 1078329344

Note that (i) the panel and both controls are displayed on the screen; (ii) I know for a fact that the outlets are properly connected, because I can do things to the controls programmatically and have them work; (iii) interface builder shows correct frame sizes in the Inspector under "Size & Position".

In short, everything else about the program is working perfectly. It actually seems that the frame dimensions aren't set properly or something.

Can somebody tell me how to retrieve the real frame information? Or at least explain the results I am seeing?

+6  A: 

The frame coordinates are floats, but your log messages are using %d. (ints).

change the NSLog string to:

@"the frame is %f, %f, %f, %f"

Edited:

Here's a very useful macro I use when debugging rects:

#define RECTLOG(rect)    (NSLog(@""  #rect @" x:%f y:%f w:%f h:%f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height ));

You can then do easy rect logs:

RECTLOG([aTextView frame]);
Kailoa Kadano
Boy, is my face red!Thanks, Kailoa. I feel dumb but I'm glad to be able to put this behind me.
Dennis
no problem. I'll add a macro that is super useful as well.
Kailoa Kadano
+3  A: 

When logging an NSRect, remember that the fields are floating point values, not integers.

Rather than writing the format specifiers yourself (either inline or via a macro), use the functions that the framework provides for you:

NSLog(@"frame - %@", NSStringFromRect([view frame]));

See also:

NSStringFromSize
NSStringFromPoint
NSStringFromRange

etc

Jim Correia
I agree. The `NSStringFrom*` methods are the best to use for `NSLog`ging. They give you some nicely formatted results.
Alex
Yes, the only problem is that NSStringFromRect generates a warning on iPhone projects. On the iPhone you have to use NSStringFromCGRect.Also, having a macro wrapper allows you to embed the variable name. Either way works though.
Kailoa Kadano
So use the type appropriate NSStringFromCGRect if you have a CGRect. It is not as if you don't know the type of the variable when you are writing the code.Also consider whether NS_BUILD_32_LIKE_64 is applicable to what you are building, and use it if appropriate.
Jim Correia