2013-01-13 9 views
14

Zrobiłem poniższą przykładową aplikację, aby zilustrować moje pytanie.Jak korzystać z autolayout z NSTableView opartym na widoku, gdy widok jest dostarczany przez NSViewController?

  • Lewy widok to widok uchwytu miejsca (dodany w programie Interface Builder). Po załadowaniu aplikacji dodaję widok podrzędny zarządzany przez NSViewController. NSViewController rysuje różne kolorowe prostokąty, z których każdy jest NSView, a układ tych kolorowych widoków zarządzanych przez ograniczenia tworzone programowo i dodawane do metody -loadView kontrolera.

  • Właściwy widok to NSTableView (dodany w Interface Builder). Po załadowaniu aplikacji korzystam z tej samej klasy NSViewController, aby udostępnić widoki dla widoku tabeli (dodano tylko jeden wiersz).

po dodaniu podrzędny w widoku uchwyt miejsce również dodać dwa dodatkowe ograniczenia,

[_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]]; 

Te ograniczenia ustawić klatkę podrzędny być równa granicach od SuperView. Wszystko jest dobrze.

Po dodaniu widoku do NSTableView przy użyciu metody delegowania -tableView:viewForTableColumn:row: widok nie został jeszcze dodany do tabeli. Jako taki nie ma superview, więc nie można (jeszcze) dodać do widoku ograniczeń. Dlatego widok w widoku tabeli nie ma tych samych granic, co komórka widoku tabeli.

Moje pytanie brzmi: jak dodać ograniczenia do widoku, który dostarczam do widoku tabeli? Czy mogę uzyskać dostęp do widoku ponownie po dodaniu go w widoku tabeli? To wydaje się trochę hack-owskie.

Two views using autolayout.

Kod źródłowy 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 

i 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 

Aktualizacja @jrturton

Dodanie ograniczenia w -(void) tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row pracował.

With constraints added.

@swalkner

Ograniczenia I dodawane są bardzo proste,

-(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]]; 
} 
+0

Jak wygląda twój 'tableView: didAddRowView: forRow:'? Chciałbym osiągnąć to samo, ale nie sprawiają, że to działa ... – swalkner

+0

Zauważając wyjątkowy. Dosłownie po prostu zastosuj ograniczenia do widoku (patrz wyżej zrobiłem dla ciebie edycję). –

Odpowiedz

6

Możesz przejść do widoku po to został dodany do tabeli w metodzie delegata tableView:willDisplayCell:forTableColumn:row: . W tym momencie możesz dodać ograniczenia, ale możesz być ostrożny, aby wciąż nie dodawać tych samych ograniczeń.

Jak się dowiedziałeś, metoda ta byłaby lepszym rozwiązaniem, ponieważ będzie ona wywoływana tylko raz dla każdego nowego widoku.

Możesz również osiągnąć ten cel, ustawiając w swoim widoku maskę automatycznego dopasowywania szerokości zamiast ograniczeń w poziomie. Tabela będzie prawdopodobnie brać to pod uwagę przy dodawaniu widoków komórek. Jeśli jesteś ostrożny, możesz łączyć i mieszać autorezjacje i wiązania.

Znam niektóre iOS, niektóre Autolayout i tylko trochę OS X, więc nie mogę dać ci znacznie więcej. Nie musimy się martwić o to, że szerokość komórek zmienia się znacznie w ziemi iOS!

+0

Dzięki za radę ze świata iOS :) Im więcej dowiaduję się o iOS, tym bardziej zazdroszczę. Wygląda to na znacznie bardziej nowoczesne API. Myślę, że OSX nadrabia zaległości. Nowości w Lion Znalazłem tableView: didAddRowView: forRow: w NSTableViewDelegate po twoich radach. –

+0

Brzmi idealnie. Zaktualizuję moją odpowiedź, aby uwzględnić tę informację, jeśli to zadziałało dla Ciebie? W ten sposób przyszli czytelnicy nie będą musieli trafiać w komentarze. – jrturton

+1

Tak, to odpowiadało na problem, tableView: didAddRowView: forRow: wydaje się być wywołana po dodaniu widoku, ale przed zakończeniem pętli uruchamiania. Dodałem ograniczenia, których potrzebowałem i wydaje się, że działają. –

Powiązane problemy