14

我制作了以下示例应用程序来说明我的问题。

  • 左视图是占位符视图(在 Interface Builder 中添加)。当应用程序加载时,我添加了一个由 NSViewController 管理的子视图。NSViewController 绘制不同颜色的矩形,每个矩形都是一个 NSView,这些颜色视图的布局由约束管理,以编程方式创建并添加到-loadView控制器的方法中。

  • 右视图是一个 NSTableView(在 Interface Builder 中添加)。当应用程序加载时,我使用相同的 NSViewController 类为表视图提供视图(仅添加一行)。

当我将子视图添加到占位符视图时,我还添加了两个额外的约束,

[_placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[CTRL_VIEW]|" options:0 metrics:nil views:views]];
[_placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[CTRL_VIEW]|" options:0 metrics:nil views:views]];

这些约束将子视图的框架设置为等于父视图的边界。一切都很好。

但是,当我使用委托方法为 NSTableView 提供视图时-tableView:viewForTableColumn:row:,该视图尚未添加到表中。因此它没有超级视图,因此不能(还)将约束添加到视图中。这就是为什么表格视图中的视图与表格视图单元格的边界不同的原因。

所以我的问题是如何向我提供给表视图的视图添加约束?表视图添加后可以再次访问视图吗?这似乎有点hack-ish。

使用自动布局的两个视图。

AppDelegate.h 的源代码,

#import <Cocoa/Cocoa.h>
@class BlahViewController;

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource, NSTableViewDelegate>

@property (assign) IBOutlet NSWindow *window;

/* Left view controller and place holding view */
@property (strong) BlahViewController *viewController;
@property (weak) IBOutlet NSView *placeholderView;

/* Right view (which is an NSTableView) */
@property (weak) IBOutlet NSTableView *tableView;


@end

和 AppDelegate.m,

#import "AppDelegate.h"
#import "BlahViewController.h"

@interface AppDelegate ()
@property NSMutableArray *tableData;
@end

@implementation AppDelegate

- (id)init
{
    self = [super init];
    if (self) {

        _tableData = [[NSMutableArray alloc] init];
        [_tableData addObject:[[BlahViewController alloc] initWithNibName:@"BlahViewController" bundle:nil]];
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints"];
    }
    return self;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    /* Add a managed subview to the place holder view*/
    _placeholderView.layer.backgroundColor = CGColorCreateGenericGray(0.5, 1.0);
    _viewController = [[BlahViewController alloc] initWithNibName:@"BlahViewController" bundle:nil];
    [_viewController.view setFrame:_placeholderView.bounds];
    [_placeholderView addSubview:_viewController.view];

    /* Additional constraints so the managed subview resizes with the place holder view */
    NSDictionary *views = @{ @"CTRL_VIEW" : _viewController.view };
    [_placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[CTRL_VIEW]|" options:0 metrics:nil views:views]];
    [_placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[CTRL_VIEW]|" options:0 metrics:nil views:views]];

}

-(NSInteger) numberOfRowsInTableView:(NSTableView *)tableView
{
    return [_tableData count];
}

-(id) tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    return [_tableData[row] view];
}


-(CGFloat) tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
    return 150.;
}

@end

更新@jrturton

-(void) tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row在工作中添加约束。

添加了约束。

@swalkner

我添加的约束非常基本,

-(void) tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row {
NSView *view = [rowView viewAtColumn:0];
NSDictionary *views = NSDictionaryOfVariableBindings(view);
[view.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-12-[view]-12-|" options:0 metrics:nil views:views]];
[view.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-12-[view]-12-|" options:0 metrics:nil views:views]];
}
4

2 回答 2

6

您可以在将视图添加到委托方法中的表后访问该视图tableView:willDisplayCell:forTableColumn:row:。此时您可以添加约束,但您可能需要注意不要一遍又一遍地添加相同的约束。

正如您自己发现的那样,该方法tableView:didAddRowView:forRow:将是一个更好的地方,因为每个新视图只会调用一次。

您也可以通过在视图上设置灵活的宽度自动调整掩码而不是任何水平尺寸约束来实现这一点。在添加单元格视图时,表格可能会考虑到这一点。如果你小心的话,你可以混合和匹配自动调整大小和约束。

我知道一些 iOS,一些 Autolayout,只有一点 OS X,所以我不能给你更多。我们不必担心 iOS 领域的单元格宽度会发生很大变化!

于 2013-01-13T07:20:55.263 回答
0

macOS 10.13 似乎包含了这个开箱即用的功能usesAutomaticRowHeights,但在 Cocoa 文档中还没有解释:

https://developer.apple.com/documentation/appkit/nstableview/2870126-usesautomaticrowheights

此外,这在 IB 中作为单元格视图高度的配置设置。

我无法验证,但也许有人可以。

于 2017-09-06T20:01:43.423 回答