EDIT: I have determined that the following happens only on an iPad Retina simulator and on my iPad Mini 3 test device. It happens 100% of the time on those targets and never on any other iPad or iPhone simulator (iPad Air/Air 2; iPad Pro; iPhone 5 through 7 Plus). I don't have any other devices for testing.
I have an app written in Swift that displays a UITableView
where I have added a UILongPressGestureRecognizer
to a custom view inside each cell. The app runs fine until I long-press on a row, at which point the app stops with
Thread 1: EXC_BAD_ACCESS (code=1, address=0xd08600b6)
(The address varies wildly and seems pretty random. Sometimes it's 0x0.) When the crash occurs, no output appears in the debug console. XCode itself opens to the first line of the class declaration for my app delegate.
I put a breakpoint at the first line of my long-press event handler method but the app crashes before the breakpoint is hit. I also added an exception breakpoint, but it does not catch the problem either.
I've enabled zombie objects in the scheme, but nothing shows up. I've tried running the app using Instruments and the zombies template; the app simply stops and Instruments doesn't flag any zombie activity. XCode's Analyze reports no problems.
I don't know how it can be relevant, but this problem is new since I first archived the app in preparation for distribution to testers. Before that, the app was working flawlessly on simulators and on a test device. The problem first showed up the first time I installed and ran the distribution .ipa file on a device. I then went back to simulator and found the same behavior. I've cleaned the project, cleaned the build folder, rebooted my development machine, and done everything I can think of to run in a pristine state. No difference.
I'm at a loss for how to make progress in tracking this down. Any suggestions would be greatly appreciated.
Further Information
It appears that the crash is happening inside the #selector
object that was passed to the UILongPressGestureRecognizer
initializer. Here's the call stack from the Debug navigator pane:
#0 0x006e7295 in objc_retain ()
#1 0x0007529f in @objc TikkunRowView.onLongPress(sender : UILongPressGestureRecognizer, forEvent : UIEvent) -> () ()
#2 0x01cc6d3b in -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] ()
#3 0x01ccf75e in _UIGestureRecognizerSendTargetActions ()
#4 0x01cccdee in _UIGestureRecognizerSendActions ()
#5 0x01ccbca8 in -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] ()
#6 0x01cb6670 in _UIGestureEnvironmentUpdate ()
And here's the code in #1 above where the crash occurs (the calll
at offset <+42>):
Tikkun Sample`@objc TikkunRowView.onLongPress(sender : UILongPressGestureRecognizer, forEvent : UIEvent) -> ():
0x60270 <+0>: pushl %ebp
0x60271 <+1>: movl %esp, %ebp
0x60273 <+3>: pushl %esi
0x60274 <+4>: subl $0x24, %esp
0x60277 <+7>: movl 0x14(%ebp), %eax
0x6027a <+10>: movl 0x10(%ebp), %ecx
0x6027d <+13>: movl 0x8(%ebp), %edx
0x60280 <+16>: movl %ecx, (%esp)
0x60283 <+19>: movl %ecx, -0x8(%ebp)
0x60286 <+22>: movl %edx, -0xc(%ebp)
0x60289 <+25>: movl %eax, -0x10(%ebp)
0x6028c <+28>: calll 0x7c9ec ; symbol stub for: objc_retain
0x60291 <+33>: movl -0x10(%ebp), %ecx
0x60294 <+36>: movl %ecx, (%esp)
0x60297 <+39>: movl %eax, -0x14(%ebp)
0x6029a <+42>: calll 0x7c9ec ; symbol stub for: objc_retain
>> 0x6029f <+47>: movl -0xc(%ebp), %ecx << CRASH HAPPENS WITH THIS LINE HIGHLIGHTED
0x602a2 <+50>: movl %ecx, (%esp)
0x602a5 <+53>: movl %eax, -0x18(%ebp)
0x602a8 <+56>: calll 0x7c9ec ; symbol stub for: objc_retain
0x602ad <+61>: movl -0x8(%ebp), %ecx
0x602b0 <+64>: movl %ecx, (%esp)
0x602b3 <+67>: movl -0x10(%ebp), %edx
0x602b6 <+70>: movl %edx, 0x4(%esp)
0x602ba <+74>: movl -0xc(%ebp), %esi
0x602bd <+77>: movl %esi, 0x8(%esp)
0x602c1 <+81>: movl %eax, -0x1c(%ebp)
0x602c4 <+84>: calll 0x5fd40 ; Tikkun_Sample.TikkunRowView.onLongPress (sender : __ObjC.UILongPressGestureRecognizer, forEvent : __ObjC.UIEvent) -> () at TikkunRowView.swift:128
0x602c9 <+89>: movl -0xc(%ebp), %eax
0x602cc <+92>: movl %eax, (%esp)
0x602cf <+95>: calll 0x7c9e6 ; symbol stub for: objc_release
0x602d4 <+100>: addl $0x24, %esp
0x602d7 <+103>: popl %esi
0x602d8 <+104>: popl %ebp
0x602d9 <+105>: retl
I'm no expert on reading this stuff, but it looks like the crash is happening in compiler-generated code that is supposed to dispatch to my event handler method. I have no idea what objects this code is checking before getting to calling my code (at offset <+84>). Here's the code I use to construct the gesture recognizer:
let g = UILongPressGestureRecognizer(target: self, action: #selector(TikkunRowView.onLongPress(sender:forEvent:)))
I don't know why the console didn't give you any detail error message. (It should!) But looking at your code, it's obviously due to the wrong signature of the gesture action callback. The following is quoted from the api doc.
The action methods invoked must conform to one of the following signatures:
- (void)handleGesture;
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;