4
votes

Using Interface Builder I have a NSView with a multi line NSTextField (a label) and directly below that, a NSComboBox. Since the height of the label is dynamic (e.g. depending on the translation used) the location of the combobox is dynamic too (as the position of the combobox is linked to the label using a constraint).

I am trying to get the correct position of the combobox AFTER auto lay-out. It must be very easy to do so but for some reason I cannot get this to work. I'm able to get the resized size of the label using [NSView fittingSize] but the [NSView frame] is returning the wrong Y position (it just returns the position used in IB). So my question is basically how to get the repositioned frame after auto-layout?

FYI, I'm requesting the frame property in the overwritten [NSView loadView] method.

Thanks for your help!

2

2 Answers

1
votes

NSView doesn't have a loadView method. Did you mean NSViewController's loadView? If so, I think that's too early to get the actual frame. You might try overriding updateConstraints and checking in there. In iOS you would do this in viewDidAppear: -- I'm not sure what the OS X equivalent of that is. Another possibility would be in viewDidMoveToWindow.

1
votes

You cloud observe your NSView's frame:

@implementation MyViewController {
    BOOL _isViewFrameKVORegistered;
}

- (void)loadView
{
    [super loadView];

    [self registerViewFrameKVO];
}

- (void)willChangeViewFrame
{
    NSLog(@"will change frame");
}

- (void)didChangeViewFrame
{
    NSLog(@"did change frame");
}

# pragma mark KVO
- (void)registerViewFrameKVO {
    [self addObserver:self forKeyPath:@"view.frame" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionPrior context:NULL];
    _isViewFrameKVORegistered = YES;
}

- (void)unregisterViewFrameKVO {
    [self removeObserver:self forKeyPath:@"view.frame"];
    _isViewFrameKVORegistered = NO;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if([keyPath isEqualToString:@"view.frame"]) {
        if ([change[@"notificationIsPrior"] boolValue]) {
            [self willChangeViewFrame];
        } else {
            [self didChangeViewFrame];
        }
    }
}

- (void)dealloc
{
    [self unregisterViewFrameKVO];
}

@end

Hope it helps.