7

Я использую UICollectionView с настраиваемой компоновкой, которая выставляет ячейки в виде сетки. Может быть более 50 строк и 50 столбцов. Прокрутка происходит как по вертикали, так и по горизонтали. В настоящее время, я делаю все настройки макета в prepareLayout и хранить его в массивах:UICollectionView Очень медленный пользовательский макет

- (void)prepareLayout { 

    NSMutableArray *newLayoutInfo = [[NSMutableArray alloc] init]; 
    NSMutableArray *newLinearLayoutInfor = [[NSMutableArray alloc] init]; 

    NSInteger sectionCount = [self.collectionView numberOfSections]; 
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; 

    self.heightForRows = [delegate collectionViewHeightForAllRows]; 

    self.totalWidthsForRows = [[NSMutableArray alloc] init]; 

    for (int i = 0; i < sectionCount; i++) { 
     [self.totalWidthsForRows addObject:[NSNumber numberWithInt:0]]; 
    } 
    for (NSInteger section = 0; section < sectionCount; section++) { 
     NSMutableArray *cellLayoutInfo = [[NSMutableArray alloc] init]; 


     NSInteger itemCount = [self.collectionView numberOfItemsInSection:section]; 

    for (NSInteger item = 0; item < itemCount; item++) { 
     indexPath = [NSIndexPath indexPathForItem:item inSection:section]; 

     UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
     itemAttributes.frame = [self frameForCellAtIndexPath:indexPath]; 

     [cellLayoutInfo addObject:itemAttributes]; 
     [newLinearLayoutInfor addObject:itemAttributes]; 
    } 
    [newLayoutInfo addObject:cellLayoutInfo]; 
} 
self.layoutInfo = newLayoutInfo; 
self.linearLayoutInfo = newLinearLayoutInfor; 
} 

Тогда в layoutAttributesForElementsInRect у меня есть:

- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { 
NSArray *rows = [self.linearLayoutInfo filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *evaluatedObject, NSDictionary *bindings) { 
    return CGRectIntersectsRect(rect, [evaluatedObject frame]); 
}]]; 

Это работает хорошо, но это лаг и нервное, когда я имеют более 50 колонок и 50 строк. Проблема теперь у меня есть то, что я должен установить

-(BOOL)shouldInvalidateLayoutForBoundsChange { 
     return YES; 
} 

Это делает его подготовить весь макет каждый раз, когда изменение границ, которые, разумеется, имеет огромное влияние на производительность, и вы едва прокрутки. Ячейки состоят только из текста с непрозрачным фоном, поэтому проблем там нет.

Я уверен, что я не делаю этого правильно и что должен быть лучший способ. Спасибо за помощь заранее.

+2

Вы должны использовать инструменты, чтобы увидеть, где вы проводите свое время во время прокрутки. – nielsbot

+0

Я рекомендую выложить элементы, поскольку они добавлены в ваш коллекционный вид. Нет необходимости в элементах компоновки, которые уже есть - они находятся в правильных положениях. Если вы сделаете это так, вы можете отключить 'shouldInvalidateLayoutForBoundsChange' – nielsbot

+0

@nielsbot У меня есть дополнительные представления, которые действуют как заголовки, которые всегда должны быть установлены на смещение содержимого коллекции. Они расположены сверху и сбоку. Если я включу 'shouldInvalidateLayoutForBoundsChange', то заголовки больше не будут« плавать »там, где они должны. Есть ли другое решение? –

ответ

0

ok - Я понимаю сейчас. Вот что я рекомендую: создайте 3 представления коллекции ... один для заголовков столбцов (где каждая ячейка является заголовком столбца), одна для лидеров строк (каждая ячейка = 1 строка) и один вид коллекции для ваших ячеек. Затем, когда пользователь просматривает позицию прокрутки любого вида коллекции, обновите позиции прокрутки для других представлений коллекции 2, если это необходимо.

enter image description here

+0

вы должны использовать Инструменты для профилирования своего приложения во время прокрутки и посмотреть, где вы проводите время процессора. Выполнение любого процессора, интенсивного в основном потоке, может привести к снижению производительности прокрутки. – nielsbot

+2

Я также сделал профилировщик, который вы можете использовать во время процедур рисования/компоновки, которые могут помочь: https://github.com/nielsbot/Profiler – nielsbot

+4

Вы шутите? 3 просмотра коллекции? Представление Collection предназначено для проектирования любого пользовательского интерфейса с его подклассом пользовательского макета. Создание 3 представлений коллекции просто означает убийство производительности приложения. –

5
-(BOOL)shouldInvalidateLayoutForBoundsChange { 
     return YES; 
} 

Причины раскладки делать prepareLayout() каждый раз, когда он прокручивает, что означает что-либо тяжелые вычисления в подготовке приведет к лагу практики, поэтому одно возможного направления, чтобы решить эту проблему, чтобы проверить, что это на самом деле принимая много времени. Одна из возможностей - это то, что находится внутри

for (NSInteger section = 0; section < sectionCount; section++) 
{ 
    // generate attributes ... 
} 

, чтобы сгенерировать атрибуты макета. Каждый раз, когда он прокручивается, каждый раз, когда это обобщение повторяется, так что он воздействует на свиток, кажется, нервный и неуклюжий. Поэтому, чтобы решить эту проблему или, по крайней мере, разобраться, что это не проблема, я предлагаю установить флаг в этом алгоритме компоновки, скажем, isScrolling, стоящий за ситуацией, когда макет должен подготовить. Каждый раз в prepareLayout() отметьте флаг, если он ДА, тогда мы будем знать, что нет необходимости делать для цикла, чтобы восстановить все атрибуты, которые alreay exsit с момента первоначальной инициализации макета.

+1

Вот почему вы должны реализовать логику в shouldInvalidateLayoutForBoundsChange, чтобы увидеть, не должно ли макет быть недействительным. return YES is evil. – Andy

9

В макете пользовательского потока я делаю это, и это, кажется, помогает:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { 
    return !(CGSizeEqualToSize(newBounds.size, self.collectionView.frame.size)); 
} 
+1

Это работает? На данный момент кажется, что вид коллекции уже имеет новый размер, поэтому он всегда равен размеру newBounds. – mattyohe

Смежные вопросы