@@ -375,31 +375,67 @@ - (UIAccessibilityElement *)accessibilityElementMatchingBlock:(BOOL(^)(UIAccessi
375375 continue ;
376376 }
377377
378- @autoreleasepool {
379- CGRect visibleRect = [collectionView layoutAttributesForItemAtIndexPath: indexPath].frame ;
380- [collectionView scrollRectToVisible: visibleRect animated: NO ];
381- [collectionView layoutIfNeeded ];
382- UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath: indexPath];
383- if (cell == nil ) {
384- [collectionView scrollToItemAtIndexPath: indexPath atScrollPosition: UICollectionViewScrollPositionNone animated: NO ];
378+ if (@available (iOS 18 , *)) {
379+ @autoreleasepool {
380+ CGRect visibleRect = [collectionView layoutAttributesForItemAtIndexPath: indexPath].frame ;
381+ [collectionView scrollRectToVisible: visibleRect animated: NO ];
385382 [collectionView layoutIfNeeded ];
386- cell = [collectionView cellForItemAtIndexPath: indexPath];
383+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath: indexPath];
384+ for (NSUInteger attempts = 0 ; attempts < 10 && !cell && collectionView.window ; attempts++) {
385+ CFRunLoopRunInMode (UIApplicationCurrentRunMode, 0.01 , false );
386+ cell = [collectionView cellForItemAtIndexPath: indexPath];
387+ }
388+ if (cell == nil ) {
389+ [collectionView scrollToItemAtIndexPath: indexPath atScrollPosition: UICollectionViewScrollPositionNone animated: NO ];
390+ [collectionView layoutIfNeeded ];
391+ cell = [collectionView cellForItemAtIndexPath: indexPath];
392+ }
393+ // Skip this cell if it can't be found
394+ if (!cell) {
395+ continue ;
396+ }
397+ UIAccessibilityElement *element = [cell accessibilityElementMatchingBlock: matchBlock notHidden: NO disableScroll: NO ];
398+
399+ // Skip this cell if it isn't the one we're looking for
400+ if (!element) {
401+ continue ;
402+ }
387403 }
388- // Skip this cell if it can't be found
389- if (!cell) {
390- continue ;
391- }
392- UIAccessibilityElement *element = [cell accessibilityElementMatchingBlock: matchBlock notHidden: NO disableScroll: NO ];
393-
394- // Skip this cell if it isn't the one we're looking for
395- if (!element) {
396- continue ;
404+
405+ // Note: using KIFRunLoopRunInModeRelativeToAnimationSpeed here may cause tests to stall
406+ CFRunLoopRunInMode (UIApplicationCurrentRunMode, CELL_SCROLL_DELAY_STABILIZATION, false );
407+ return [self accessibilityElementMatchingBlock: matchBlock disableScroll: NO ];
408+ } else {
409+ @autoreleasepool {
410+ // Get the cell directly from the dataSource because UICollectionView will only vend visible cells
411+ UICollectionViewCell *cell = [collectionView.dataSource collectionView: collectionView cellForItemAtIndexPath: indexPath];
412+
413+ // The cell contents might change just prior to being displayed, so we simulate the cell appearing onscreen
414+ if ([collectionView.delegate respondsToSelector: @selector (collectionView:willDisplayCell:forItemAtIndexPath: )]) {
415+ [collectionView.delegate collectionView: collectionView willDisplayCell: cell forItemAtIndexPath: indexPath];
416+ }
417+
418+ UIAccessibilityElement *element = [cell accessibilityElementMatchingBlock: matchBlock notHidden: NO disableScroll: NO ];
419+
420+ // Remove the cell from the collection view so that it doesn't stick around
421+ [cell removeFromSuperview ];
422+
423+ // Skip this cell if it isn't the one we're looking for
424+ // Sometimes we get cells with no size here which can cause an endless loop, so we ignore those
425+ if (!element || CGSizeEqualToSize (cell.frame .size , CGSizeZero)) {
426+ continue ;
427+ }
397428 }
429+
430+ // Scroll to the cell and wait for the animation to complete
431+ CGRect frame = [collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath: indexPath].frame ;
432+ [collectionView scrollRectToVisible: frame animated: YES ];
433+ // Note: using KIFRunLoopRunInModeRelativeToAnimationSpeed here may cause tests to stall
434+ CFRunLoopRunInMode (UIApplicationCurrentRunMode, 0.5 , false );
435+
436+ // Now try finding the element again
437+ return [self accessibilityElementMatchingBlock: matchBlock];
398438 }
399-
400- // Note: using KIFRunLoopRunInModeRelativeToAnimationSpeed here may cause tests to stall
401- CFRunLoopRunInMode (UIApplicationCurrentRunMode, CELL_SCROLL_DELAY_STABILIZATION, false );
402- return [self accessibilityElementMatchingBlock: matchBlock disableScroll: NO ];
403439 }
404440 }
405441
0 commit comments