Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to use autolayout with view-based NSTableView when view are provided by an NSViewController?
    primarykey
    data
    text
    <p>I have made the following example app to illustrate my question.</p> <ul> <li><p>The left view is a place holder view (added in Interface Builder). When the App loads I add a subview managed by a NSViewController. The NSViewController draws the different coloured rectangles, each of which is a NSView, and the layout of these coloured views managed by constraint created programmatically and added to the <code>-loadView</code> method of the controller.</p></li> <li><p>The right view is an NSTableView (added in Interface Builder). When the App loads I use the same NSViewController class to provide views to for the table view (only one row is added).</p></li> </ul> <p>When I add the subview the the place holder view I also add two additional constraints,</p> <pre><code>[_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]]; </code></pre> <p>These constraints set the frame of the subview to be equal to the bounds of the superview. All is good.</p> <p>However, when I provide the view for the NSTableView using the delegate method <code>-tableView:viewForTableColumn:row:</code>, the view has not yet been added to the table. As such it doesn't have a superview, so constraints cannot (yet) be added to the view. This is why the view in the table view does not have the same bounds as the table view cell.</p> <p>So my question is how can I add constraints to the view I supply to the table view? Can I access the view again after the table view has added it? This seems a bit hack-ish.</p> <p><img src="https://i.stack.imgur.com/dOp0U.png" alt="Two views using autolayout."></p> <p>The source code for the AppDelegate.h,</p> <pre><code>#import &lt;Cocoa/Cocoa.h&gt; @class BlahViewController; @interface AppDelegate : NSObject &lt;NSApplicationDelegate, NSTableViewDataSource, NSTableViewDelegate&gt; @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 </code></pre> <p>and AppDelegate.m,</p> <pre><code>#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 </code></pre> <p><strong>Update @jrturton</strong></p> <p>Adding the constraints in <code>-(void) tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row</code> worked.</p> <p><img src="https://i.stack.imgur.com/5m4m7.png" alt="With constraints added."></p> <p><strong>@swalkner</strong></p> <p>The constraints I added are very basic,</p> <pre><code>-(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]]; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload