NSCollectionView не прокручивает элементы за начальный видимый прямоугольник

У меня возникла проблема с существующим приложением, когда я пытаюсь исправить несколько неполадок в macOS 10.13. У меня есть небольшой NSCollectionView, который похож на небольшой ежемесячный календарь в приложении «Календарь». Он отображает дни и прокручивается вертикально при нажатии. Однако в macOS 10.13 представление коллекции отображает только несколько строк и не прокручивается. Я проверил, что источник данных вызывается правильно и пытается загрузить дополнительные элементы, но не прокручивает их.

Я создал небольшой пример приложения, который также демонстрирует проблему. Это базовое приложение macOS, которое добавляет NSCollectionView через основную раскадровку и имеет общий класс NSCollectionViewItem, загружаемый из пера. Весь код в контроллере основного вида:

- (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;  
}

Получившееся приложение выглядит так:

введите описание изображения здесь

К сожалению, это полностью представление коллекции. Прокрутка не прокручивает дополнительные элементы. Я загрузил пример приложения на https://www.dropbox.com/sh/wp2y7g0suemzcs1/AABVKfTZq54J7riy6BR7Mhxha?dl=0 на случай, если это окажется полезным. Любые идеи, почему это ломается на 10.13 для меня?


person ppilone    schedule 26.09.2017    source источник
comment
У меня есть небольшой NSCollectionView, который похож на небольшой ежемесячный календарь в приложении «Календарь». Если это так, то зачем вам 2000 предметов?   -  person El Tomato    schedule 27.09.2017
comment
Представление коллекции календарей находится в моем рабочем приложении и предназначено только для контекста. Образец приложения, который я собрал, использует 2000 элементов, потому что это случайное число, которое я выбрал, чтобы иметь представление коллекции с достаточным количеством элементов, требующих прокрутки.   -  person ppilone    schedule 27.09.2017
comment
Привет, ты нашел решение этой проблемы? Я думаю, что сталкиваюсь с той же проблемой в High Sierra.   -  person Z S    schedule 26.10.2017
comment
У меня есть несколько похожая проблема, но в 10.13.1 ваше приложение работает нормально и правильно прокручивается для меня.   -  person Tap Forms    schedule 07.11.2017
comment
В MacOS 10.14 представление коллекции работает без этого исправления, пока я не установлю (начальный) выбор в viewDidLoad, используя selectItemsAtIndexPaths:scrollPosition: это исправление решает проблему и в этом случае.   -  person Gerrit Beuze    schedule 16.01.2019
comment
Примечание. В моем аналогичном случае (хотя решение setFrameSize не работает для меня) это происходит только в том случае, если для параметра «Системные настройки» Показать полосы прокрутки: установлено значение «При прокрутке», но не «Всегда». См. stackoverflow.com/questions/57374020.   -  person Thomas Tempelmann    schedule 06.08.2019


Ответы (4)


У меня была аналогичная проблема с прокруткой NSCollectionView под управлением High Sierra. Вот как я решил это:

СВИФТ

  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];
  }
person rihurla    schedule 08.11.2017
comment
Спасибо за фрагмент, он решает проблему для меня. Кто-нибудь знает, что вызывает это? У меня есть NSCollectionView, у которых нет этой проблемы в 10.13, но есть у других. Я не могу точно определить, почему это влияет только на определенные NSCollectionView - person Austin; 09.04.2018
comment
Это может быть сразу после настройки представления вашей коллекции (viewDidLoad, viewWillAppear). - person rihurla; 26.09.2018
comment
Кажется, что это ломается при постоянном отображении полос прокрутки, поскольку полосы прокрутки перекрывают элементы представления коллекции (вместо того, чтобы вызывать повторное расположение). - person goetz; 24.10.2019

У меня была похожая проблема на macOS 10.14. У меня был вызов, чтобы установить выбор в -viewDidLoad:

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

что вызвало сломанный макет. Я смог решить проблему, переместив этот вызов на -viewWillAppear.

person goetz    schedule 24.10.2019

Мое решение состоит в том, что если я могу показать collectionView обычным образом, я встраиваю viewController в окно. Если мне нужно всплывающее окно, я использую следующее для своего ViewController:

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

}

Вы должны изменить одно (или оба) значения, не важно какое.

person green_knight    schedule 18.07.2020

В моей macOS Mojave 10.14.4 с использованием Xcode 10.2 NSCollectionView не будет прокручиваться, пока я не добавлю в свое приложение собственный NSWindowController. Я позаимствовал следующий viewDidLoad из учебника Рэя Вендерлиха, который можно найти здесь https://www.raywenderlich.com/783-nscollectionview-tutorial. Я не знаю, почему это работает, но это работает.

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)
    }
}
person ByteByByte    schedule 13.04.2019
comment
Embed-in-WindowController работает для «показных» переходов, но вы не можете показывать окно как всплывающее окно. - person green_knight; 18.07.2020