Crash occurs when interacting with UITextFields contained in UITableViewCells that do not use cell reuse

Originator:emaloney
Number:rdar://15265608 Date Originated:10/18/2013
Status:Open Resolved:9/15/2014
Product:iOS SDK Product Version:7.0
Classification:Crash/Hang/Data Loss Reproducible:Always
 
I'm working on an application that does not use table cell reuse because we have another way of caching cell contents.

However, starting with iOS 7, if a cell does not have a reuse identifier (i.e. its constructor was passed 'nil' for the 'reuseIdentifier'), a crash will occur when interacting with UITextFields.

The crash is reproducible 100% of the time when the table is large enough for some of the cells containing UITextFields to scroll offscreen.

(A sample project is attached containing code that will trigger the crash.)

Steps to Reproduce:
1. Download and unzip the Xcode project files contained in the attachment to this ticket.

2. Open the "TableCellCrashScenario.xcodeproj" project.

3. Run the iPhone app in the simulator.

4. Interact with some of the text fields on the screen by entering data.

5. Scroll the text fields you've entered some information in offscreen.

6. Attempt to click in one of the empty fields onscreen.

7. If that does not crash the application, attempt to type into some more of the empty text fields. Repeat steps 5-7 until a crash occurs.

I am able to cause the crash 100% of the time by repeating this process. The crash almost always occurs within the first 15 seconds or so of performing these steps.

Expected Results:
Expect that a crash would not occur.

Actual Results:
A crash occurs both in the simulator and on device with a stack trace similar to:

* thread #1: tid = 0x2de658, 0x014c80b2 libobjc.A.dylib`objc_msgSend + 14, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x7000000c)
    frame #0: 0x014c80b2 libobjc.A.dylib`objc_msgSend + 14
    frame #1: 0x00385ec3 UIKit`-[UIResponder(Static) _setFirstResponder:] + 83
    frame #2: 0x00385ead UIKit`-[UIResponder(Static) _setFirstResponder:] + 61
    frame #3: 0x00385ead UIKit`-[UIResponder(Static) _setFirstResponder:] + 61
    frame #4: 0x00385ead UIKit`-[UIResponder(Static) _setFirstResponder:] + 61
    frame #5: 0x00385495 UIKit`-[UIResponder(Internal) _resignFirstResponder] + 41
    frame #6: 0x00907acc UIKit`-[UITextField _resignFirstResponder] + 261
    frame #7: 0x0038471e UIKit`-[UIResponder _finishResignFirstResponder] + 181
    frame #8: 0x00384846 UIKit`-[UIResponder resignFirstResponder] + 288
    frame #9: 0x00907894 UIKit`-[UITextField resignFirstResponder] + 118
    frame #10: 0x00384550 UIKit`-[UIResponder becomeFirstResponder] + 347
    frame #11: 0x00287d0b UIKit`-[UIView(Hierarchy) becomeFirstResponder] + 114
    frame #12: 0x009070e3 UIKit`-[UITextField becomeFirstResponder] + 51
    frame #13: 0x005ac651 UIKit`-[UITextInteractionAssistant(UITextInteractionAssistant_Internal) setFirstResponderIfNecessary] + 135
    frame #14: 0x005aeba2 UIKit`-[UITextInteractionAssistant(UITextInteractionAssistant_Internal) oneFingerTap:] + 2640
    frame #15: 0x005a2f8c UIKit`_UIGestureRecognizerSendActions + 230
    frame #16: 0x005a1c00 UIKit`-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 383
    frame #17: 0x005a366d UIKit`-[UIGestureRecognizer _delayedUpdateGesture] + 60
    frame #18: 0x005a6bcd UIKit`___UIGestureRecognizerUpdate_block_invoke + 57
    frame #19: 0x005a6b4e UIKit`_UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 317
    frame #20: 0x0059d248 UIKit`_UIGestureRecognizerUpdate + 199
    frame #21: 0x00269d4a UIKit`-[UIWindow _sendGesturesForEvent:] + 1291
    frame #22: 0x0026ac6a UIKit`-[UIWindow sendEvent:] + 1030
    frame #23: 0x0023ea36 UIKit`-[UIApplication sendEvent:] + 242
    frame #24: 0x00228d9f UIKit`_UIApplicationHandleEventQueue + 11421
    frame #25: 0x016be8af CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    frame #26: 0x016be23b CoreFoundation`__CFRunLoopDoSources0 + 235
    frame #27: 0x016db30e CoreFoundation`__CFRunLoopRun + 910
    frame #28: 0x016dab33 CoreFoundation`CFRunLoopRunSpecific + 467
    frame #29: 0x016da94b CoreFoundation`CFRunLoopRunInMode + 123
    frame #30: 0x036869d7 GraphicsServices`GSEventRunModal + 192
    frame #31: 0x036867fe GraphicsServices`GSEventRun + 104
    frame #32: 0x0022b94b UIKit`UIApplicationMain + 1225
    frame #33: 0x000030ed TableCellCrashScenario`main(argc=1, argv=0xbfffeeb8) + 141 at main.m:16
    frame #34: 0x01d71725 libdyld.dylib`start + 1


Version:
Xcode 5 (5A1413) running iOS 7.0 in the simulator (11A465) and iOS 7.0.2 on device (11A501).

Notes:


Configuration:
Crash occurs on every simulator and device tested that runs any version of iOS 7.

Attachments:
'TableCellCrashScenario.zip' was successfully uploaded.

Comments

Fixed in iOS 8 GM

This issue has been fixed by Apple; the fix is available as of the iOS 8 GM release.

Since OpenRadar doesn't take attachments the way bugreport.apple.com does, here's the key portion of the code

//
//  TableViewController.m
//  TableCellCrashScenario
//
//  Created by Evan Maloney on 10/18/13.
//

#import "TableViewController.h"

@interface TableViewController () <UITableViewDataSource, UITableViewDelegate>
@end

@implementation TableViewController

- (void) viewDidLoad
{
    [super viewDidLoad];

    UITableView* table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    table.delegate = self;
    table.dataSource = self;
    [self.view addSubview:table];
}

- (NSInteger) numberOfSectionsInTableView:(UITableView*)tableView
{
    return 1;
}

- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    return 100;
}

- (UITableViewCell*) tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];

    CGRect editingRect = CGRectInset(cell.contentView.frame, 5, 5);
    UITextField* text = [[UITextField alloc] initWithFrame:editingRect];
    text.borderStyle = UITextBorderStyleBezel;
    [cell.contentView addSubview:text];

    return cell;
}

@end

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!