performSelector throws UIViewControllerHierarchyInconsistency exception - iphone

I was developing my application on XCode 4.1, for iOs 4.3, but yesterday I've updated it to XCode 4.2 with iOs 5.0 SDK.
When I run my application in iphone 4.3 simulator, it works great.
I decided to test it on iphone 5.0 simulator, and following problems appeared:
I've got a view controller f.e "MyViewController", and a custom class which implements some custom component "MyCustomComponent" which is added to "MyViewController". There is a button in MyCustomComponent, and when its touched it peformSelector from MyViewController, and it leads to crash with EXC_BAD something. Same code works on iPhone 4.3 simulator just perfectly. Any ideas?
Custom navigation bar - doesn't work at all. I'm trying to set custom background implementing UINavigationBar, and overriding drawRect, but it doesn't shows in ios 5.

OK, so i guess I figrued it out. My console was off, when i reinstalled xcode, so didn't see any error messages. Turned it on now, and got an error
Terminating app due to uncaught exception
'UIViewControllerHierarchyInconsistency'
Problem was that I was adding MyCustomComponent to MyViewController using
self.view=myCustomComponent.view
when I should be doing
[self.view addSubview:myCustomCoponent.view]
it wasn't an issue in ios 4.3, but seems its a big deal in ios 5.

I struggled with the same problem.
When you create a new Master-Detail Application(without story board), you can see this codes below from AppDelegate.m.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
"BE NOT DEPENDENT ON MainWindow"
Just start from your own ViewController and set it to delegate.
And don't forget to unlink view from MainWindow.xib else the view will called 2 times.

EXC_BAD_ACCESS implies that the object doesn't exist. Try NSLog-ging the object on which you are performing the performSelector-method.
EDIT: If it crashes when you try logging it, it has been dealloced. Check if you retain the object correctly!
If it is a valid object, try:
if(![obj respondsToSelector:#selector(mySelector:)]){NSLog(#"no such method!");}

Related

iOS - Testing view controllers

I've got a really weird and unexplainable problem and it's like the whole day I'm trying to fix it without any result.
I have setup a testing target for my iOS project, following the doc steps.
I'm using Xcode Version 4.5.2 (4G2008a).
I'm also using kiwi. Every test works fine, apart when it comes to load the view of a view controller with xib.
The view controller is a simple UIViewController with a MKMapView, a button and a searchbar, all properly hooked to the owner's IBOutlets.
In the test I'm writing something like:
__block MapViewController *mapVC = [[MapViewController alloc] initWithNibName:#"MapViewController"
bundle:[NSBundle bundleWithIdentifier:#"com.myorg.MyAppTest"]];
it(#"Loads the view", ^{
[mapVC loadView];
});
While executing the test (on iPhone Simulator 5.0) I get a bunch of these in the console:
ERROR: System image table has not been initialized. Do not ask for
images or set up UI before UIApplicationMain() has been called.
After that I almost always get this error
[__NSCFType pointSize]: unrecognized selector sent to instance
0x19cb970
On iPhone 6 Simulator I get initially this error
Unknown Device Type. Using UIUserInterfaceIdiomPhone based on screen
size
Followed by this
-[__NSCFType screenFontWithRenderingMode:]: unrecognized selector sent to instance 0xeba1540
I hope someone can help me, this thing is driving me mad.

Works on iOS Simulator but not on iPhone

The line of code works fine on the iOS Simulator 6.0, but is crashing when I try to run it on my iPhone, also running iOS6.
[menuView addSubview:mvc.view];
Why is this happening, and how can I fix it?
This is the more complete version of the code:
SDMenuViewController *mvc = [[SDMenuViewController alloc] init];
[menuView addSubview:mvc.view];
And this is what it is crashing with:
2012-10-08 21:32:32.423 CrunchCalculator1-2[21019:907] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </var/mobile/Applications/EDD23933-CE20-4AFD-A2B1-CDD56AD658E8/CrunchCalculator1-2.app> (loaded)' with name 'SDNestedTableView''
*** First throw call stack:
(0x39cd03e7 0x35ece963 0x39cd0307 0x39ee0fd1 0x39ee05ff 0x39dd9031 0x39e0786d 0x39d63419 0xb20d9 0x39d63541 0x39da3d29 0x39d9fac5 0x39de1199 0xb17c5 0x39da4a71 0x39da45f5 0x39d9c803 0x39d44ce7 0x39d44775 0x39d441b7 0x31e145f7 0x31e14227 0x39ca53e7 0x39ca538b 0x39ca420f 0x39c1723d 0x39c170c9 0x39d9b43d 0x39d98289 0xb1523 0x3792fb20)
libc++abi.dylib: terminate called throwing an exception
Thanks!
I'm not quite sure how it worked on your simulator (when I tried it on mine, I got the crash you list in your original question). Anyway, you can fix it by looking at the following items:
The main problem is that the NIB was not included in the bundle. Add it to the project target's "Copy Bundle Resources", e.g.:
While you're looking at your "Copy Bundle Resources", you'll also want to include SDSubCell.xib, SDGroupCell.xib, and add all of those PNG files, too.
As an aside, while it doesn't apparently cause the crash, the "File Owner" base class in SDNestedTableView NIB refers to a class that doesn't exist anywhere in this project. That can't be good. Anyway, you probably want to change that to SDMenuViewController or SDNestedTableViewController;
It's a little unrelated to your crash, but as I look at the project, I see a worrying construct:
SDMenuViewController *mvc = [[SDMenuViewController alloc] initWithNibName:#"SDNestedTableView" bundle:nil];
[menuView addSubview:mvc.view];
You're creating a controller, grabbing its view, and either letting the view controller fall out of scope and be released (if you were using ARC) or leaking it (if not ARC).
I wasn't entirely sure from the original question whether you were doing addSubview as a way of transitioning to a new view (which is really bad practice) or whether you were doing view controller containment. As I look at the code, it appears you're doing the latter, though you're missing a few calls in your code. You might want to read up on view controller containment. And also check out that WWDC 2011 session 102.
Anyway, those two lines of code above with the view controller alloc/init and the subsequent addSubview will leak in your non-ARC project (and would crash it if you ever went to ARC) and your view hierarchy is out of sync with your view controller hierarchy. I'd suggest you might want:
SDMenuViewController *mvc = [[[SDMenuViewController alloc] initWithNibName:#"SDNestedTableView" bundle:nil] autorelease];
[self addChildViewController:mvc];
[mvc didMoveToParentViewController:self];
[menuView addSubview:mvc.view];
Note the autorelease on that first line.
View controller containment can be powerful, but you want to make sure you do some of this basic housekeeping.
One final update:
I notice that there are some bugs that are in this code. First, your use of currentSection in item:setSubItem:forRowAtIndexPath won't work. You're setting that based upon the last expandingItem. So, if you click on one of the main items before expanding either one, the program will crash. Probably best is to eliminate the currentSection variable altogether and in item:setSubItem:forRowAtIndexPath, use item.cellIndexPath.row rather than your variable currentSection.
Unfortunately, this fix leads to a more serious problem, there appears to be an iOS 6 bug in the SDNestedTable class, itself. If you run this on iOS 6 and you expand your all of your items, scroll to the bottom and then scroll back to the top, the program will crash because the cellIndexPath property of the SDGroupItem *item returned by item:setSubItem:forRowAtIndexPath can be deallocated! If you turn on zombies in iOS 6, you'll see cellIndexPath has been released. I went and downloaded the original version and see the same problem there. The problem appears to be that cellIndexPath in SDGroupCell is defined as an assign property (which means that if iOS determines it no longer needed the indexPath it created for its own purposes, it will be released even though SDGroupCell maintains an assign reference to this released object). Just change the cellIndexPath property of SDGroupCell from assign to retain, and this iOS 6 bug goes away. I've informed the developer of SDNestedTable of this issue, but this change to retain will fix the problem of the code crashing in iOS 6.
[Edit: The author of SDNestedTable agreed with my assessment of the issue, and he reports that this issue has been fixed the latest version. - Rob]
Best wishes.
You should probably use initWithNibName: insead of just init in the first line. Not sure regarding your specific issue, but certainly something to try.
It looks like you're trying to instantiate a nib called SDNestedTableView.nib and it isn't present. Is the nib included as a project member?

-(void)viewWillDisappear:(BOOL)animated method didnot called in ios sdk 5 but called in ios sdk4

I have got this issue that -(void)viewWillDisappear:(BOOL)animated method is getting called when I run this view in 4.3 simulator but it's not called when I am running the app in 5.0 and more simulator.
Can you explain why?
I have tried to replicate this but in my case its calling viewWillDisappear: in both cases
(simulator4.3 and 5.0)This is what I have done
1> created new projected
2> added a UIbutton in viewWillAppear:
3> on btn clicked presenting new controller modally using presentModalVIewController:(BOOL)animated
every time it present new controller
it is calling viewWillDiappear:(BOOL)animated of parent controller

Xcode 4 - viewDidLoad issue

Is anyone else having issues with Xcode 4 where viewDidLoad is being called twice? I have run the same project in both Xcode 3.2 and Xcode 4 and it only acts up in Xcode 4.
After researching this on the Apple Developer forums, it seems that in some cases Xcode 4 creates bugged Interface Builder NIBs. The effect is that the application's rootViewController gets loaded in twice, which really screws things up. The same project loaded in Xcode 3 won't exhibit the problem.
In my universal app, it only affected the iPad NIB. The iPhone was fine.
I was able to solve this issue by:
Removing the rootViewController connection in Interface Builder (this causes the app to load with window.rootViewController = nil)
In viewDidLoad for the main controller (the one that was being loaded twice), I then manually assign appDelegate.window.rootViewController = self
So far this seems to have the desired effect.
Xcode is just the IDE -- it shouldn't have any bearing on what happens when your app is executing. If there's a difference, it seems more likely that you're building for different iOS versions.
Did you set the view of the view controller? I had the same issue and I realized that I didn't set the view property.
- (void)viewDidLoad {
UIView *contentView = [[UIView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame];
//add some stuff to contentView here
self.view = contentView;
[contentView release];
}
I had same issue. And i resolved it. It happens when your app memory did get memory warning.
Put a breakpoint to memoryDidReceiveWarning. It get's called, and clear your class object memory. So your viewDidLoad Get called twice, because it has no memory at that time.

iPhone App view fails to load in iPad but loads in iPhone simulator

I am simulating an "iPhone-only" app in iPad. The binary simulates fine in the iPhone simulator, but when attempting to simulate in the iPad, the initial background image appears, but then the screen just goes black. (Xcode v4.1, SDK 4.1)
The app has only one view, which is controlled by a single custom UIViewController. (SoloViewController) The only view managed by SoloViewController is contained in a "detached" nib called "mainview.xib".
I initialize the SoloViewController in my AppDelegate like so:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
SoloViewController *vc = [[SoloViewController alloc] initWithNibName:#"mainview" bundle:[NSBundle mainBundle]];
self.soloViewController=vc;
[vc release];
[window addSubview:[soloViewController view]];
[window makeKeyAndVisible];
}
My Info.plist file has the "Main nib file base name" set to "MainWindow", which I believe is the default Xcode gives you when you first create a ViewController-based project. Anyway, I just left that as-is. However, when attempting to simulate in iPad, the log says:
Failed to load NSMainNibFile MainWindow.
iPhone simulator and hardware have no problem with this...
If I set the "Main nib file base name" key to "mainview" to use the xib file for the view, I get this error:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIApplication 0x7a01270> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key view.'
I've double-checked the xib in IB and all of the outlets are properly defined and connected to SoloViewController.h & SoloViewController.m. What am I doing wrong here!?
Also - if I leave the NSMainNibFile blank, then the iPhone simulator just comes up with a black screen. (no errors in log)
As it turns out the project, in this case requires a MainWindow.xib file. In my case, I had inadvertently removed this file from the original project template and thought it was ok, since it simulated and ran fine in hardware. (iPhone) The MainWindow.xib file requires a File's Owner of type "UIApplication", First Responder of type "UIResponder", an App Delegate of a custom type pointing to your application delegate. (name will vary depending on what you've named your project) Lastly there is a Window of type UIWindow. All of these are default settings, with exception of the App Delegate.
Once I included a xib configured this way, the app loads as expected in both iPhone & iPad simulators. (Still not clear as to why the iPad simulator treats the absence of the MainWindow.xib file differently)
Similar behavior can happen when you reference constants in your code (or via IB code-generation) that are defined in iOS 4x or later, while the iPad runs 3.2x, and knows nothing of these key definitions.
Make sure your target has the iOS Deployment Target set to iOS 3.2 and the Base SDK to 4.1. If you changed these values, do a clean before recompiling. Unfortunately, I don't think you'll see a compiler warning in this case.
Hope that helps.