0
votes

In my document based OS X app, I have an empty NSScrollView in the xib, with "show vertical scroller" set. At run time I generate a view with buttons for navigation, which I set as the document view for the NSScrollView. Most of the time, this works well, but about 25% of the time, seemingly at random (or at least I can't reproduce any particular condition yet!), instead of a scroller on the side, I get a black bar where the scroller should be. If I resize the window, the black bar disappears, the scroller appears and works fine.

The result is that if I open six or seven blank documents, one after the other, about 3 of them will not have immediately functioning scrollviews.

Here is the code that creates the view with the navigation buttons, and adds it as the NSScrollview's documentView.

YMScrollDocView is a subclass of NSView that sets isFlipped to YES. navScrollView is the outlet to the scrollview in xib.

 float allHeight = 0.f; // Consider starting from the top
//float xOffset = 2.f; // Offset addjustments
float spacing = 4.f; // Spacing
float buttonCellHeight = 40.f;

YMScrollDocView *navView = [[YMScrollDocView alloc]init];

//1
NSButton *overviewButton = [[NSButton alloc]initWithFrame:NSMakeRect(0, allHeight, self.navScrollView.bounds.size.width, buttonCellHeight)];

[overviewButton setTitle:@"Overview"];
[overviewButton setButtonType:NSMomentaryLight];
[overviewButton setBordered:NO];
[[overviewButton cell]setBackgroundColor:[self colorWithHexColorString:@"30BDF8"]];
[overviewButton setBezelStyle:NSRegularSquareBezelStyle];
[overviewButton setButtonType:NSCellIsBordered];
[overviewButton setTarget:self];
[overviewButton setAction:@selector(goToOverview)];
[overviewButton setRefusesFirstResponder:YES];
[navView addSubview:overviewButton];
allHeight += buttonCellHeight;
allHeight += spacing;


//2
NSButton *curriculumButton = [[NSButton alloc]initWithFrame:NSMakeRect(0, allHeight, self.navScrollView.bounds.size.width, buttonCellHeight)];

[curriculumButton setTitle:@"Curriculum"];
[curriculumButton setButtonType:NSMomentaryLight];
[curriculumButton setBordered:NO];
[[curriculumButton cell]setBackgroundColor:[self colorWithHexColorString:@"36FBF8"]];
[curriculumButton setBezelStyle:NSRegularSquareBezelStyle];
[curriculumButton setButtonType:NSCellIsBordered];
[curriculumButton setTarget:self];
[curriculumButton setAction:@selector(goToCurriculum)];
[curriculumButton setRefusesFirstResponder:YES];
[navView addSubview:curriculumButton];
allHeight += buttonCellHeight;
allHeight += spacing;

(I add more buttons with repetitive code here, then finish with the following code.)

[navView setFrame:NSMakeRect(1, 1, self.navScrollView.bounds.size.width, allHeight)];
[[self navScrollView]setDocumentView:navView];
2
I think you should let your embedded view be whatever size it wants to be (don't size it to the size of the scollview). The scrollview will worry about the rest.trojanfoe
I switched that out, giving the embedded view a set width, but I'm still getting the same behavior.Steven Hovater

2 Answers

0
votes

I ran your code(slightly modified to see scrollbars). What properties did you set on the NSScrollView in Interface Builder? Also where are you setting up the document view, etc?(your above code). I initialized them all in the below method of the NSDocument and it all works fine!

- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
    [super windowControllerDidLoadNib:aController];

    float allHeight = 0.f; // Consider starting from the top
    float spacing = 4.f; // Spacing
    float buttonCellHeight = 4000.f;

    CustomView *navView = [[CustomView alloc]init];
    //1
    NSButton *overviewButton = [[NSButton alloc]initWithFrame:NSMakeRect(0, allHeight, _scrollView.bounds.size.width, buttonCellHeight)];

    // Setup overviewButton properties
    [navView addSubview:overviewButton];
    allHeight += buttonCellHeight;
    allHeight += spacing;

    //2
    NSButton *curriculumButton = [[NSButton alloc]initWithFrame:NSMakeRect(0, allHeight, _scrollView.bounds.size.width, buttonCellHeight)];

    // setup curriculumButton properties
    [navView addSubview:curriculumButton];
    allHeight += buttonCellHeight;
    allHeight += spacing;

    [navView setFrame:NSMakeRect(1, 1, _scrollView.bounds.size.width, allHeight)];
    [_scrollView setDocumentView:navView];
}
0
votes

I still haven't completely resolved this issue, but I have come up with a hacky solution that I thought I'd share. Right now, I'm calling a separate method to resize the window immediately after launch. This is at the end of windowControllerDidLoadNib:

[self performSelector: @selector(resizeWidth) withObject: nil afterDelay:0.0f];

This calls:

-(void)resizeWidth
{
NSRect newFrame = NSMakeRect(oldFrame.origin.x, oldFrame.origin.y, 975, oldFrame.size.height);
[[self docWindow]setFrame:newFrame display:YES animate:YES];
}

I don't love this solution, particularly as it creates a very small animation that catches the user's eye, but it is very quick, often unnoticeable and always less intrusive than the original issue. At least this way the app's scrollers are immediately available to the user, and the UI functions without requiring the user to resize the window.