@@ -303,48 +303,50 @@ - (UIAccessibilityElement *)accessibilityElementMatchingBlock:(BOOL(^)(UIAccessi
303
303
} else if ([self isKindOfClass: [UICollectionView class ]]) {
304
304
UICollectionView *collectionView = (UICollectionView *)self;
305
305
306
- NSArray *indexPathsForVisibleItems = [collectionView indexPathsForVisibleItems ];
307
-
306
+ NSMutableArray *indexPathsForVisibleItems = [[NSMutableArray alloc ] init ];
307
+ [[collectionView visibleCells ] enumerateObjectsUsingBlock: ^(UICollectionViewCell *cell, NSUInteger idx, BOOL *stop) {
308
+ NSIndexPath *indexPath = [collectionView indexPathForCell: cell];
309
+ if (indexPath) {
310
+ [indexPathsForVisibleItems addObject: indexPath];
311
+ }
312
+ }];
313
+
314
+ CFTimeInterval delay = 0.05 ;
308
315
for (NSUInteger section = 0 , numberOfSections = [collectionView numberOfSections ]; section < numberOfSections; section++) {
309
- for (NSUInteger item = 0 , numberOfItems = [collectionView numberOfItemsInSection: section]; item < numberOfItems; item ++) {
316
+ for (NSUInteger row = 0 , numberOfItems = [collectionView numberOfItemsInSection: section]; row < numberOfItems; row ++) {
310
317
if (!self.window ) {
311
318
break ;
312
319
}
313
320
314
- // Skip visible items because they are already handled
315
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem: item inSection: section];
321
+ // Skip visible rows because they are already handled.
322
+ NSIndexPath *indexPath = [NSIndexPath indexPathForItem: row inSection: section];
316
323
if ([indexPathsForVisibleItems containsObject: indexPath]) {
317
- continue ;
324
+ @autoreleasepool {
325
+ // scroll to the last row of each section before continuing. Attemps to ensure we can get to sections that are off screen. KIF tests (e.g. testButtonAbsentAfterRemoveFromSuperview) fails without this line. Also without this... we can't expose the next section (in code downstream)
326
+ [collectionView scrollToItemAtIndexPath: [indexPathsForVisibleItems lastObject ] atScrollPosition: UICollectionViewScrollPositionNone animated: NO ];
327
+ continue ;
328
+ }
318
329
}
319
-
320
- @autoreleasepool {
321
- // Get the cell directly from the dataSource because UICollectionView will only vend visible cells
322
- UICollectionViewCell *cell = [collectionView.dataSource collectionView: collectionView cellForItemAtIndexPath: indexPath];
323
330
324
- // The cell contents might change just prior to being displayed, so we simulate the cell appearing onscreen
325
- if ([collectionView.delegate respondsToSelector: @selector ( collectionView:willDisplayCell:forItemAtIndexPath: )]) {
326
- [collectionView.delegate collectionView: collectionView willDisplayCell: cell forItemAtIndexPath: indexPath];
327
- }
331
+ @autoreleasepool {
332
+ // Scroll to the cell and wait for the animation to complete. Using animations here may not be optimal.
333
+ CGRect sectionRect = [collectionView layoutAttributesForItemAtIndexPath: indexPath]. frame ;
334
+ [collectionView scrollRectToVisible: sectionRect animated: NO ];
328
335
336
+ // wait for it to scroll before checking for cell
337
+ CFRunLoopRunInMode (UIApplicationCurrentRunMode, delay, false );
338
+
339
+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath: indexPath];
329
340
UIAccessibilityElement *element = [cell accessibilityElementMatchingBlock: matchBlock notHidden: NO ];
330
-
331
- // Remove the cell from the collection view so that it doesn't stick around
332
- [cell removeFromSuperview ];
333
-
341
+
334
342
// Skip this cell if it isn't the one we're looking for
335
- // Sometimes we get cells with no size here which can cause an endless loop, so we ignore those
336
- if (!element || CGSizeEqualToSize (cell.frame .size , CGSizeZero )) {
343
+ if (!element) {
337
344
continue ;
338
345
}
339
346
}
340
-
341
- // Scroll to the cell and wait for the animation to complete
342
- CGRect frame = [collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath: indexPath].frame ;
343
- [collectionView scrollRectToVisible: frame animated: YES ];
347
+
344
348
// Note: using KIFRunLoopRunInModeRelativeToAnimationSpeed here may cause tests to stall
345
- CFRunLoopRunInMode (UIApplicationCurrentRunMode, 0.5 , false );
346
-
347
- // Now try finding the element again
349
+ CFRunLoopRunInMode (UIApplicationCurrentRunMode, delay, false );
348
350
return [self accessibilityElementMatchingBlock: matchBlock];
349
351
}
350
352
}
0 commit comments