14

私の質問を説明するために、次のサンプルアプリを作成しました。

  • 左側のビューはプレースホルダー ビューです (Interface Builder で追加)。アプリが読み込まれると、NSViewController によって管理されるサブビューを追加します。NSViewController は、それぞれが NSView であるさまざまな色の四角形を描画し、これらの色付きのビューのレイアウトは、プログラムで作成され-loadView、コントローラーのメソッドに追加された制約によって管理されます。

  • 右側のビューは NSTableView (Interface Builder で追加) です。アプリが読み込まれると、同じ NSViewController クラスを使用して、テーブル ビューにビューを提供します (1 行のみが追加されます)。

サブビューをプレース ホルダー ビューに追加するときに、さらに 2 つの制約を追加します。

[_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:、ビューはまだテーブルに追加されていません。そのため、スーパービューがないため、(まだ) 制約をビューに追加することはできません。これが、テーブル ビューのビューがテーブル ビュー セルと同じ境界を持たない理由です。

私の質問は、テーブルビューに提供するビューに制約を追加するにはどうすればよいですか? テーブル ビューがビューを追加した後、ビューに再度アクセスできますか? これは少しハックっぽいです。

自動レイアウトを使用した 2 つのビュー。

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うまくいきました。

制約が追加されました。

@スウォークナー

私が追加した制約は非常に基本的なもので、

-(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:は新しいビューごとに 1 回だけ呼び出されるため、より適切な場所になります。

水平方向のサイズ制限の代わりに、ビューに柔軟な幅の自動サイズ変更マスクを設定することで、これを達成できる場合もあります。セル ビューを追加するとき、テーブルはおそらくこれを考慮に入れます。注意すれば、自動サイズ変更と制約を組み合わせて一致させることができます。

私はいくつかの iOS、いくつかの Autolayout、そして OS X を少ししか知らないので、それ以上のことは言えません。iOS ランドではセル幅が大きく変わることを心配する必要はありません。

于 2013-01-13T07:20:55.263 に答える