8
votes

I'm running into an issue with an existing app while trying to fix a few outstanding macOS 10.13 bugs. I have a small NSCollectionView that looks similar to the small monthly calendar in the Calendar app. It displays days and scrolls vertically on click. However, on macOS 10.13 the collection view only displays a few rows and does not scroll. I've verified that the data source is being called correctly and it does try to load additional items - but doesn't scroll to them.

I've created a small sample application that also demonstrates the issue. This is a basic macOS app that adds an NSCollectionView via the Main storyboard and has a generic NSCollectionViewItem class loaded from a nib. The entirety of the code in the main view controller is:

- (void)viewDidLoad {  
  [super viewDidLoad];  

  NSNib *nib = [[NSNib alloc] initWithNibNamed:@"FooCollectionViewItem" bundle:nil];  
  [self.collectionView registerNib:nib forItemWithIdentifier:@"foo"];  
}  
- (void)viewDidAppear {  
  [super viewDidAppear];  

  [self.collectionView reloadData];  
}  
- (void)setRepresentedObject:(id)representedObject {  
  [super setRepresentedObject:representedObject];  

}  
- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)collectionView {  
  return 1;  
}  
- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {  
  return 2000;  
}  
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {  
  FooCollectionViewItem *item = [collectionView makeItemWithIdentifier:@"foo" forIndexPath:indexPath];  
  item.fooField.stringValue = [NSString stringWithFormat:@"%ld", indexPath.item];  

  return item;  
}

The resulting app looks like:

enter image description here

Unfortunately, that's the entirely of the collection view. Scrolling doesn't scroll through any additional items. I've uploaded the sample app to https://www.dropbox.com/sh/wp2y7g0suemzcs1/AABVKfTZq54J7riy6BR7Mhxha?dl=0 in case that's useful. Any ideas why this is breaking on 10.13 for me?

4
"I have a small NSCollectionView that looks similar to the small monthly calendar in the Calendar app." If that's the case, then why do you need 2,000 items?El Tomato
The calendar collection view is in my production app and was just meant for context. The sample app I put together uses 2000 items because that's the random number I picked in order to have a collection view with enough items that required scrolling.ppilone
Hi, did you find a solution to this? I think I'm running into the same issue on High Sierra.Z S
I'm having a somewhat similar problem, but in 10.13.1, your app runs fine and scrolls properly for me.Tap Forms
On MacOS 10.14 the collectionview works without this fix until I set the (initial) selection in viewDidLoad using selectItemsAtIndexPaths:scrollPosition: This fix then solves the problem also in that case.Gerrit Beuze

4 Answers

16
votes

I had a similar issue with NSCollectionView scroll running High Sierra. Here's how I solved it:

SWIFT

  if #available(OSX 10.13, *) {
    if let contentSize = self.collectionView.collectionViewLayout?.collectionViewContentSize {
      self.collectionView.setFrameSize(contentSize)
    }
  }

OBJ-C

  if (@available(macOS 10.13, *)) {
    [self.collectionView setFrameSize: self.collectionView.collectionViewLayout.collectionViewContentSize];
  }
1
votes

I had a similar problem on macOS 10.14. I had a call to set the selection in -viewDidLoad:

[self.collectionView selectItemsAtIndexPaths:[NSSet setWithCollectionViewIndexPath: indexPath] scrollPosition:NSCollectionViewScrollPositionNone];

which caused the broken layout. I was able to fix the problem by moving this call to -viewWillAppear.

1
votes

My solution is that if I can show the collectionView ordinarily, I embed the viewController in a window. If I want a popover, I use the following for my ViewController:

    override func viewDidAppear() {
self.view.setFrameSize(NSSize(width: self.view.frame.size.width, height: self.view.frame.size.height + 1))

}

You have to change one (or both) values, it does not matter which one.

0
votes

On my macOS Mojave 10.14.4, using Xcode 10.2, the NSCollectionView would not scroll until I added a custom NSWindowController to my app. I borrowed the following viewDidLoad from the Ray Wenderlich tutorial found here https://www.raywenderlich.com/783-nscollectionview-tutorial. I don't know why it works, but it does.

override func windowDidLoad() {
    super.windowDidLoad()
    if let window = window, let screen = NSScreen.main {
        let screenRect = screen.visibleFrame
        window.setFrame(NSRect(x: screenRect.origin.x, y: screenRect.origin.y, width: screenRect.width/2.0, height: screenRect.height), display: true)
    }
}