10

UPDATE

This is an old question for an old version of Xcode. It turned out that the issue was a bug in Xcode which has been fixed.

Original

I have a storyboard generated from making a new tab iphone application (with ARC)

In one of my tabs, if I drag a gesture recognizer (any, but let's say Pan) onto a control, and then set the selector to an action, it just crashes as soon as I go to the tab.

There is nothing in the Console -- it appears to be happening while the storyboard is being loaded (viewDidLoad is never called).

  1. I can't figure out how to get more information
  2. On a different tab, this works fine. Both tabs were generated automatically.

(it's possible I messed something up in the view, but I don't have a clue to figuring out what I did).

If I make gestures programmatically, they work fine, but it's nice to have it work in the storyboard, and I'm afraid that whatever is wrong will cause a crash some other way at some point.

MORE INFO

In the simulator I get

-[__NSCFString setView:]: unrecognized selector sent to instance 0x6d2db70

Again, need debugging techniques -- for example, is there a way to find out what object 0x6d2db70 is?

Which is exactly like this question (with no answer):

Gesture recognizer in Interface builder crashes my app

MORE INFO

This is trivial to reproduce

  1. New iPhone tabbed application, ARC and Storyboard on
  2. Drag tap gesture onto second tab's view (works on first one)
  3. Create an (IBAction)
  4. Connect the gesture's selector connection to the action from #3
  5. run, go to second tab

Crashes. Same thing with my app, default tab works, other tabs don't

Community
  • 1
  • 1
Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • 1
    What kind of crash? SIGABRT? EXC_BAD_ACCESS? What's the stack trace? – rob mayoff Jan 27 '12 at 15:38
  • That's the thing -- console has nothing. Stack trace is back at main in the release pool (so it feels like memory corruption). Need ideas for getting more info. – Lou Franco Jan 27 '12 at 15:59
  • I have done a LOT of iPhone debugging, but new to 4.2, ARC, etc. I would like ideas for new techniques (I know about zombies, debug malloc, etc -- but they don't seem appropriate). – Lou Franco Jan 27 '12 at 16:00
  • Also, is there a connection that I need to make besides selector? Does it connect to an IBAction with (id) sender? I can't seem to find any good docs on this. – Lou Franco Jan 27 '12 at 16:01
  • The action method signatures are documented [here](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIGestureRecognizer_Class/Reference/Reference.html). The method can take a sender parameter or not. – rob mayoff Jan 27 '12 at 16:08
  • 2
    A stack trace pointing at main usually indicates that an exception was thrown. Do you have an exception breakpoint set? – rob mayoff Jan 27 '12 at 16:08
  • 1
    Besides setting the recognizer's target and action, it needs to be in at least one view's `gestureRecognizers` outlet collection. You do that by dropping the recognizer on a view. But it should be harmless if it's not in any `gestureRecognizers` collections. – rob mayoff Jan 27 '12 at 16:10
  • Not near my computer right now -- will check all of this when I get to it -- thanks. @rob, add an answer -- I think you've given me enough to solve -- I will edit it with the results. Thanks. – Lou Franco Jan 27 '12 at 17:27
  • It's trivial to reproduce -- I think it's a bug – Lou Franco Jan 28 '12 at 20:30
  • Check that the target of the Gesture Recognizer is not deallocated – onmyway133 Jun 02 '15 at 07:08

2 Answers2

9

The error message tells us that the program is sending the setView: message to an instance of __NSCFString (which is obviously the private implementation class of NSString).

Make sure you have tried running with zombies enabled. A zombie can easily cause an unrecognized selector error.

If it's not a zombie, put a breakpoint on -[NSObject doesNotRecognizeSelector:]. When the breakpoint is hit, you may be able to figure out the problem just from the stack trace. If not, you can print the debugDescription of the object (which is the same as the description for most classes).

On the simulator, you can ask the debugger to print the object's debugDescription like this:

(gdb) frame 0
#0  0x013bcbff in -[NSObject doesNotRecognizeSelector:] ()
(gdb) po ((int*)$ebp)[2]
this is my test string

On the device, you do this:

(gdb) frame 0
#0  0x344bca22 in -[NSObject doesNotRecognizeSelector:] ()
(gdb) po $r0
this is my test string

Update

Based on your steps to reproduce, this is a bug in UIKit. File a bug report. You can work around the bug by creating a strong outlet on SecondViewController and connecting it to the gesture recognizer. Make sure you set the outlet to nil in viewDidUnload.

Update

Do not ever set your outlet to nil -- part of the bug is that UIKit isn't retaining -- you need to keep your reference to make sure that the recognizers aren't released.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • turning on zombies says the tap gesture is a zombie. -[UITapGestureRecognizer retain]: message sent to deallocated instance 0x6b5ba80 – Lou Franco Jan 28 '12 at 19:55
  • I just noticed that UIImageView doesn't have a gestureRecognizers collection -- I have other UIImageView's where gestures work (also has the IB warning in the inspector). – Lou Franco Jan 28 '12 at 19:57
  • The `gestureRecognizers` property is part of `UIView`, so `UIImageView` inherits it. It is not tagged `IBOutletCollection`, so it only shows up in IB if you drop a recognizer on a view. – rob mayoff Jan 28 '12 at 20:20
  • Do you have any `unsafe_unretained` outlets or variables? – rob mayoff Jan 28 '12 at 20:22
  • Or any `assign` properties? Under ARC, `assign` is the same as `unsafe_unretained`. – rob mayoff Jan 28 '12 at 20:23
  • It's trivial to reproduce -- I think it's a bug (see updated question) – Lou Franco Jan 28 '12 at 20:30
  • Everything is strong -- I have a trivial project that repros it. No outlets or any variables – Lou Franco Jan 28 '12 at 20:38
  • That's exactly what I did -- glad that you agree. I am using ARC -- do I need to set the outlet to nil? – Lou Franco Jan 28 '12 at 22:14
  • This was assigned Problem ID: 10771117 by Apple -- I will update this question if I hear that it was fixed – Lou Franco Jan 28 '12 at 22:22
  • 1
    You need to set the outlet to nil in viewDidUnload. Otherwise it won't get released on a memory warning. – rob mayoff Jan 28 '12 at 23:43
  • Unfortunately, you cannot release in viewDidUnload -- when the memory warning comes, the app will crash because UIKit isn't keeping a retain -- you have to hold yours (you can see this by setting to nil in viewDidUpload and simulating a memory warning -- you will crash when you change tabs with a zombie warning) – Lou Franco Jan 31 '12 at 18:52
  • 2
    Wow! I have been experiencing this issue as well, and it wasn't until I reviewed the Device Log in Organizer and found the doesNotRecognizeSelector was caused by the swipe that I managed to find this page. I have the same issue, and the fix above worked (just ctrl+drag the swipe gesture on to the header file of the backing view controller and make it a Strong Outlet - problem solved). Thanks! – Shaun McCarthy Mar 27 '12 at 03:55
2

In my case, when auto-creating the IBOutlet for the gesture recognizer by drag-n-dropping in the code, Xcode correctly created the property with a "strong" attribute, but it also added the "set to nil" in viewDidUnload. Removing the "set to nil" solved the issue for me.

Ben G
  • 3,965
  • 3
  • 30
  • 34