UITableViewDelegate method called with indexPath=nil when running UI tests

Originator:kraina
Number:rdar://31375101 Date Originated:31 March 2017
Status:open Resolved:
Product:iOS SDK Product Version:10.0
Classification: Reproducible:
 
The 'public func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool' method when implemented in a class that conforms UITableViewDelegate gets sometimes called by the system with nil for the 'indexPath' parameter.

As the indexPath parameter is bridged from Objective-C as implicitly unwrapped, this causes a crash and makes the test fail with the following error: 

Assertion Failure: UI Testing Failure - Failure getting snapshot Error Domain=XCTestManagerErrorDomain Code=9 "Error -25204 getting snapshot for element AXUIElement 0x7f84b5c0ea40 {pid=32894}" UserInfo={NSLocalizedDescription=Error -25204 getting snapshot for element AXUIElement 0x7f84b5c0ea40 {pid=32894}}


App's backtrace on crash:

(lldb) thread backtrace
* thread #1: tid = 0x128eaa, 0x000000010c776c3a libswiftFoundation.dylib`static Foundation.IndexPath._unconditionallyBridgeFromObjectiveC (Swift.Optional<__ObjC.NSIndexPath>) -> Foundation.IndexPath + 42, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x000000010c776c3a libswiftFoundation.dylib`static Foundation.IndexPath._unconditionallyBridgeFromObjectiveC (Swift.Optional<__ObjC.NSIndexPath>) -> Foundation.IndexPath + 42
    frame #1: 0x0000000108443241 Static`@objc DataSource.tableView(UITableView, canPerformAction : Selector, forRowAt : IndexPath, withSender : Any?) -> Bool + 97 at DataSource.swift:0
    frame #2: 0x00000001095aea31 UIKit`-[UITableView _canPerformAction:forCell:sender:] + 169
    frame #3: 0x00000001098017c6 UIKit`-[UITableViewCell canPerformAction:withSender:] + 86
    frame #4: 0x00000001210a5fc9 UIKit`-[UIResponder(UITextAccessibilityUtilities) _accessibilityHasTextOperations] + 100
    frame #5: 0x000000012107bb7c UIKit`-[UITableViewCellAccessibilityElement _accessibilityHasTextOperations] + 48
    frame #6: 0x00000001211f09ec UIAccessibility`-[NSObject(AXPrivCategory) accessibilityAttributeValue:] + 5945
    frame #7: 0x000000012120bc04 UIAccessibility`_accessibilityAttributesForObject + 767
    frame #8: 0x000000012120b5e8 UIAccessibility`-[NSObject(UIAccessibilityAutomation) _accessibilityUserTestingSnapshotDescendantsWithAttributes:maxDepth:maxChildren:maxArrayCount:] + 1736
    frame #9: 0x000000012120cf96 UIAccessibility`-[NSObject(UIAccessibilityAutomation) _accessibilityUserTestingSnapshotWithOptions:] + 557
    frame #10: 0x00000001211eec0a UIAccessibility`-[NSObject(AXPrivCategory) accessibilityAttributeValue:forParameter:] + 7903
    frame #11: 0x00000001211d8856 UIAccessibility`_copyParameterizedAttributeValueCallback + 211
    frame #12: 0x0000000120869532 AXRuntime`_AXXMIGCopyParameterizedAttributeValue + 216
    frame #13: 0x0000000120863f1c AXRuntime`_XCopyParameterizedAttributeValue + 440
    frame #14: 0x0000000120872de5 AXRuntime`mshMIGPerform + 266
    frame #15: 0x00000001064e93d9 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    frame #16: 0x00000001064e9351 CoreFoundation`__CFRunLoopDoSource1 + 465
    frame #17: 0x00000001064e1435 CoreFoundation`__CFRunLoopRun + 2389
    frame #18: 0x00000001064e0884 CoreFoundation`CFRunLoopRunSpecific + 420
    frame #19: 0x000000010e5bda6f GraphicsServices`GSEventRunModal + 161
    frame #20: 0x000000010943dc68 UIKit`UIApplicationMain + 159
    frame #21: 0x000000010462c95f GoOut`main + 111 at AppDelegate.swift:47
    frame #22: 0x000000010cb7e68d libdyld.dylib`start + 1
    frame #23: 0x000000010cb7e68d libdyld.dylib`start + 1


Additional notes:
Interestingly, on iOS 9 simulator this works just fine, no crashes. It's the iOS 10 and above that's problematic

Expected results:
This problematic UITableViewDelegate's method should either not be called at all with indexPath=nil or the indexPath type should be marked as optional:

'public func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath?, withSender sender: Any?) -> Bool'

Comments

Possible cause

Ran into this as well. It appears to happen if you create two cells in cellForRowAt... Might double check that all paths only create one cell.

By chwielands at April 5, 2017, 4:04 p.m. (reply...)

Workaround

Use optional IndexPath? type for the indexPath parameter. The method gets called properly and does not crash.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!