views:

967

answers:

6

Basically the problem is exactly what the title says.

My app works smoothly on the simulator, with no crashes whatsoever. In fact, the previous version is on the app store. I made minor changes here and there and suddenly it started to crash in a very odd place.

I use [NSBundle mainBundle] resourcepath] in various places in the code to access plist files, images, etc. The first few calls to NSBundle mainBundle] are totally normal-as expected-, however, at some point it returns...

-[NSBundle < null selector>]: unrecognized selector sent to instance 0x10a0e0

...and crashes on the device. Here is the exact code snippet:

-(void) setImageName:(NSString *)s
{
 [imageName release];
 imageName = [s copy];
 NSLog(@"last line before crash"); 
 NSString *imagePath =[[NSBundle mainBundle] resourcePath];
 NSLog(@"Why would it crash before here???"); 

    imagePath = [imagePath stringByAppendingString:imageName];
    imageUI = [[UIImage alloc] initWithContentsOfFile:imagePath];
    [self setNeedsDisplay];
}

To check if that call is really the problem, I saved resourcePath into a string in the first ever call to [NSBundle mainbundle] in the project (the first few calls were totally normal as I stated above) and used that resourcePath string everywhere I needed [NSbundle mainbundle] and voila! no crashes/ leaks, nothing...

I'm totally confused.. Why would that call crash my app on the device but not the simulator?

Edit: using...

NSArray *array = [NSBundle allBundles];
NSBundle *bundle = [array objectAtIndex:0];
NSString *imagePath = [bundle bundlePath];

...instead of [[NSBundle mainBundle] resourcePath] works too. I guess somehow I'm doing something affecting this particular call only.

Edit 2: Here is the backtrace when I set a breakpoint in -[NSObject doesNotRecognizeSelector:] :

#0  0x30e27b98 in -[NSObject doesNotRecognizeSelector:]
#1  0x30dacb18 in ___forwarding___
#2  0x30da3840 in __forwarding_prep_0___
#3  0x0000bcfe in -[CustomTableViewCell setImageName:] at CustomTableViewCell.m:93
#4  0x0000499e in -[RootTableViewController tableView:willDisplayCell:forRowAtIndexPath:] at RootTableViewController.m:469
#5  0x3364d5d0 in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:]
#6  0x3364cde0 in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:]
#7  0x335f832c in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow]
#8  0x335f6514 in -[UITableView layoutSubviews]
#9  0x335f22d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#10 0x32bac1c0 in -[CALayer layoutSublayers]
#11 0x32babedc in CALayerLayoutIfNeeded
#12 0x32bab844 in CA::Context::commit_transaction
#13 0x32bab474 in CA::Transaction::commit
#14 0x32bb35dc in CA::Transaction::observer_callback
#15 0x30da1830 in __CFRunLoopDoObservers
#16 0x30de9346 in CFRunLoopRunSpecific
#17 0x30de8c1e in CFRunLoopRunInMode
#18 0x332e7374 in GSEventRunModal
#19 0x335adc30 in -[UIApplication _run]
#20 0x335ac230 in UIApplicationMain

... Where #3 - CustomTableViewCell.m:93 is NSString *imagePath =[[NSBundle mainBundle] resourcePath]; in the part of the code I posted above.

+1  A: 

Basically the problem is exactly what the title says. - No it is not. I can guarantee you that [NSBundle mainBundle] is not the reason for the crash. The crash is a symptom of something you are doing wrong in another part of your code. Like for example bad memory management.

St3fan
well i agree with you there must be an error somewhere but why dont i see no crashes when i use a predefined string instead of [[nsbundle mainbundle] resourcepath] in that particular code snippet? and isnt the error -[NSBundle < null selector>] itself really strange?
ahmet emrah
Yes it points to memory corruption I think.
St3fan
+4  A: 

Turn on NSZombieEnabled and you'll see where the problem really is.

Kendall Helmstetter Gelner
my very most favorite flag upon entrance to the iphone objective-c world. a necessity for the (unusual) paradigm that is apples implementation of this language.
KevinDTimm
I will be interested to see if this actually works. The error Ahmet reports is not usually associated with bad memory management, but it's hard to see what else could be at fault.
Chuck
thx for the answer but i already tried nszombie and didnt get anyting in addition to -[NSBundle < null selector>]:
ahmet emrah
A: 

One possible problem is that if, for some reason, you happen to pass the same imageName twice, you'll release it before you retain it. You might want to change the first two lines to:

if (imageName != s) {
    [imageName release];
    imageName = [s retain]; 
}
Ben Gottlieb
thx, but im closely following memory allocation of imagename.
ahmet emrah
+1  A: 

Be aware that hard coding path strings into your document is not a good idea. Your path changes (ususally with each build). As far as your crash goes, it's hard to know without seeing more code. But take a look at this suggestion:

instead of

 [imagePath stringByAppendingString:imageName]; 

you should be using

 [imagePath stringByAppendingPathComponent:imageName];

stringByAppendingPathComponent is suited especially for dealing with paths and filenames.

JustinXXVII
thx, i tried that already, in fact i commented out that part and left [[nsbundle mainbundle] resourcepath] unused and still saw the crash
ahmet emrah
+1  A: 

A crash on device but not the simulator (and vice versa) is usually caused by a compiled library/framework that is complied for one hardware platform but not the other. Since the simulator runs on intel and the device on arm, this causes odd crashes. Check anything you may have added, especially anything you didn't compile recently.

The error -[NSBundle < null selector>]: unrecognized selector sent to instance 0x10a0e0 suggest that for whatever reason the NSBundle class has "forgotten" it has a mainBundle method. Note that it is the selector which is null and not the object as we would expect in a memory related error. That suggest some high level corruption somewhere.

I would put the following log before any calls to [NSBundle mainBundle];

NSLog(@"responds to selector mainBundle=%@",[NSBundle respondsToSelector:@selector(mainBundle)]?@"YES":@"NO");

This will tell you if it really is suddenly losing the mainBundle selector.

Edit01:

Thanks for your answer. It seems Nsbundle states it can respond to mainbundle: "responds to selector mainBundle=YES", just before the crashing call to [NSBundle mainBundle]

Hmmm, the crash must be bad enough to cause the wrong error code return. That suggest that the problem might be in the lines immediately before or after the call to mainBundle.

Given that the crash occurs in CustomTableViewCell, I'm going to guess it's a problem in a nib. Do you have a subclass of UITableViewCell defined in a nib? Do you have an image defined in the nib? What file type is it? Does the same error occur with a different image or a different nib?

I do think that the key clue is that it works on the simulator but not on the device. You need to look for things that would behave differently based on the hardware.

You've certainly got a hard one here.

TechZen
Thanks for your answer. It seems Nsbundle states it can respond to mainbundle: "responds to selector mainBundle=YES", just before the crashing call to [NSBundle mainBundle].
ahmet emrah
See my Edit01 for more ideas.
TechZen
The problem actually is harder. It's not that particular part of the project, i.e. CustomTableViewCell, that causes crash. I remove CustomTableViewCell from the project, using standard cells instead, and yet again the next call to [NSBundle mainbundle] in the project, -wherever it is- causes crash, and as i stated in the original post, [NSBundle allBundles] approach works. Actually I'm not stuck with this error, ive moved on just after i first posted here, nonetheless im keen to learn what would cause the error, thats why i'm keeping the crashing version and applying things suggested here.
ahmet emrah
I'm stumped and out of ideas.
TechZen
Not that I'm complaining but why is this the correct answer? It appears that I was wrong on all accounts. We don't want to confuse somebody in the future looking at the post. You might want to update with the solution to make it clear.
TechZen
Nothing suggested in this thread worked, and my problem definitely is NOT simple retain/release operations addressed in other answers.
ahmet emrah
A: 

You should be able to do [NSBundle mainBundle] just about anytime. How about putting it scattered about your code to catch the first time it breaks, hopefully close to something that break the memory management (ie a memory corruption happening) as St3fan states can be the problem.

epatel