手动实现 NSTabViewController 的 Rect Transition 及 Propagate Title

 • 

不知为何 我在 OS X 10.11.5 及 Xcode 7.3 的 Storyboard 中设置 Tab View Controller 的 Transition 属性时,Tab View Controller 并不能自动根据子 View Controller 的 Preferred Content Size 来动画渐变,因此只能自己实现了(包括 Propagate Title)。

目前的 Storyboard 设置:
记得关掉 Propagate Title,因为在我的 build 上没有任何用处,而且还影响后面通过 Delegate 手动设置标题。

Step 1:
Subclass TabView Controller,这里是JZSettingsTabViewController,加上 NSTabViewDelegate

Step 2:
实现协议,

- (void)updateWindowSizeWithItem:(NSTabViewItem *)item
{
    NSWindow *window = self.view.window;
    NSSize contentSize = item.viewController.preferredMinimumSize;
    NSSize newWindowSize = [window frameRectForContentRect:(CGRect){CGPointZero, contentSize}].size;
    
    NSRect frame = [window frame];
    frame.origin.y += frame.size.height;
    frame.origin.y -= newWindowSize.height;
    frame.size = newWindowSize;
    [self.view.window setFrame:frame display:YES animate:YES];
    window.title = item.label;
}

Step 3:
既然上面是通过 preferredMinimumSize 获取的 Size,那么在子 View Controller 的实现文件里加上这句,这个时候就不要写 Preferred Content Size 了:

- (CGSize)preferredMinimumSize
{
    return CGSizeMake(500, 400);
}

虽然这样 Size 就不是通过 Storyboard 设置了略嫌麻烦,不过考虑到 TabView Controller 的每个子 VC 都肯定要实现的,也还算可以。
我这里是因为要写 设置界面 所以用到了 NSTabViewController 并且保持固定的 Window 大小(通过去除 NSResizableWindowMask),如果需要一个可以 Resize 的 Window 同时保持不同 Tab 的大小切换动画,

NSSize contentSize = item.viewController.preferredMinimumSize;

这句可以适当修改,比如修改为当前拉伸后的预期大小。