Как использовать автозапуск с помощью NSTableView на основе представления, когда представление предоставляется NSViewController? - программирование
Подтвердить что ты не робот

Как использовать автозапуск с помощью NSTableView на основе представления, когда представление предоставляется NSViewController?

Я сделал следующее примерное приложение, чтобы проиллюстрировать мой вопрос.

  • Левое представление - это вид места размещения (добавлен в Interface Builder). Когда приложение загружается, я добавляю subview, управляемый NSViewController. NSViewController рисует разные цветные прямоугольники, каждый из которых представляет собой NSView, а макет этих цветных представлений управляется с помощью ограничения, созданного программно и добавленного к методу -loadView контроллера.

  • Правильный вид - это NSTableView (добавлено в Interface Builder). Когда приложение загружается, я использую один и тот же класс NSViewController для представления представлений для представления таблицы (добавляется только одна строка).

Когда я добавляю subview в представление владельца места, я также добавляю два дополнительных ограничения,

[_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:, представление еще не добавлено в таблицу. Таким образом, он не имеет супервизора, поэтому ограничения не могут (пока) быть добавлены в представление. Вот почему представление в представлении таблицы не имеет тех же границ, что и ячейка представления таблицы.

Итак, мой вопрос в том, как я могу добавить ограничения для представления, которое я предоставляю в виде таблицы? Могу ли я получить доступ к представлению снова после того, как табличное представление добавило его? Это кажется немного взломанным.

Two views using autolayout.

Исходный код для 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.

With constraints added.

@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]];
}
4b9b3361

Ответ 1

Вы можете получить доступ к представлению после его добавления в таблицу в методе делегата tableView:willDisplayCell:forTableColumn:row:. На этом этапе вы можете добавить ограничения, но вы можете быть осторожны, чтобы не продолжать добавлять одни и те же ограничения снова и снова.

Как вы выяснили, метод tableView:didAddRowView:forRow: был бы лучшим местом, так как это будет вызвано только один раз для нового представления.

Вы также можете достичь этого, установив гибкую ширину авторезистирующей маски на вашем представлении вместо ограничений по горизонтальному размеру. Вероятно, таблица учитывает это при добавлении ячеек. Если вы осторожны, вы можете смешивать и сопоставлять авторезистентность и ограничения.

Я знаю некоторые iOS, некоторые Autolayout и только небольшую OS X, поэтому я не могу дать вам гораздо больше. Нам не нужно беспокоиться о том, что ширина ячеек сильно меняется на земле iOS!

Ответ 2

macOS 10.13, кажется, включает эту возможность из коробки с usesAutomaticRowHeights, но она еще не имеет объяснения в документах Cocoa:

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

Кроме того, это показано в IB в качестве параметра конфигурации на высоте представления ячеек.

Я не смог проверить, но может быть, кто-то может.