I can't seem to figure out how to get the content inside a NSScrollView to scale properly. I have come across a few references which describe general approaches, but nothing concrete.
This seems to indicate that NSScrollView and Auto Layout don't play nicely together. It is somewhat telling that both the iOS & OSX Auto Layout guide examples are UIScrollView instead of NSScrollView:
I threw together an example. The main window contains a split view with some fixed content on the right and a view that will be filled in programmatically on the left. (I would post a picture, but I don't have the required reputation yet). Running the code below, any attempt to move the splitter will result in it snapping back to the original position.
AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (weak) IBOutlet NSScrollView *scrollView;
@property (strong, nonatomic) NSView *containerView;
@property (strong, nonatomic) NSMutableDictionary *views;
@property (assign) IBOutlet NSWindow *window;
@end
AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize scrollView;
@synthesize containerView;
@synthesize views;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
-(void)awakeFromNib {
// Create a container to hold all the subviews
containerView = [[NSView alloc] initWithFrame:NSZeroRect];
[containerView setTranslatesAutoresizingMaskIntoConstraints:NO];
[scrollView setDocumentView:containerView];
views = [[NSMutableDictionary alloc] init];
for (int i=0; i<8; i++) {
NSBox *box = [[NSBox alloc] init];
NSString *title = [NSString stringWithFormat:@"Box%@", [[NSNumber numberWithInt:i] stringValue]];
box.title = title;
[views setObject:box forKey:title];
[box setTranslatesAutoresizingMaskIntoConstraints:NO];
[containerView addSubview:box];
}
long height = 160;
NSArray *sortedKeys = [[views allKeys] sortedArrayUsingSelector: @selector(compare:)];
for(NSString *viewName in sortedKeys) {
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:[[NSString alloc] initWithFormat:@"|-20-[%@]-20-|", viewName] options:0 metrics:nil views:views]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:[[NSString alloc] initWithFormat:@"V:[%@(==%ld)]",viewName, height] options:0 metrics:nil views:views]];
}
// Build the subview-to-subview constraint string
NSString *constraintString = @"V:|";
for(NSString *viewName in sortedKeys) {
constraintString = [constraintString stringByAppendingString:[NSString stringWithFormat:@"-20-[%@]",viewName]];
}
// Subview-to-subview constraints
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:constraintString options:0 metrics:nil views:views]];
// Container view constraints
NSDictionary *topLevelDictionary = NSDictionaryOfVariableBindings(containerView);
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-0-[containerView]-0-|" options:0 metrics:nil views:topLevelDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[containerView]" options:0 metrics:nil views:topLevelDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:[[NSString alloc] initWithFormat:@"V:|[containerView(==%ld)]", (long)(20 + height) * sortedKeys.count + 20] options:0 metrics:nil views:topLevelDictionary]];
}
@end
Any direction would be greatly appreciated.