Setting window root viewcontroller Bad access without stack trace - objective-c

Edit: It seems this was a stupid mistake by me, i got a rotationChanged notification too early, before i could process it. That caused a chain reaction which caused a crash in some obscure location. Let me see how i can close/delete this question...
My app's been working fine for a while, but i decided today to finally implement it 'correctly', that is: Use a view controller instead of manually adding a single view to the UIWindow. This went quite smooth for a while, untill i tried setting window.rootViewController to my view controller.
Somewhere after applicationDidFinishLaunchingWithOptions, it crashes with a bad access. There's no useful stacktrace (it crashes in the assembly), and i can't see it getting back into my code anywhere (i placed logs all over the place). Just adding the viewcontroller's view to the main window works fine. This is the part of the code:
-(BOOL) application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
....
self.window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
self.viewController = [[MainViewController alloc]init];
// if i uncomment this it crashes:
// self.window.rootViewController = self.viewController;
[self.window addSubview: viewController.view]; // Commented out if i use the rootViewController
[self.window makeKeyAndVisible];
NSLog(#"Did finish launching");
return YES;
}
I've tried quite some debugging methods (stacktrace does not exist, stepping through the code manually takes forever, logs are not being called before the crash), but i can't find the problem. It crashes in libobjc.A.dylib'objc_retain:, and the only other thing in the stacktrace is objc_storeStrong. It's not a retain/release problem (at least not directly), since i'm using ARC. The final NSLog is called and it gets out of the didFinishLaunching if i step through manually.
I can get the app working without setting the root view controller, but the whole point of redoing this part was to do everything 'proper' (e.g. rotation has to be done relatively hackish without the root view controller).
so StackOverflow, please tell me you have some ideas! As this is driving me crazy :S

You don't need to do this:
[self.window addSubview: viewController.view];
When you set the view controller as root view controller, it's view already becomes subview of the window.
EDIT
However this wouldn't cause any problem.
Maybe the problem isn't in the code. Sometimes my apps crash too, and I get mad. Usually this happens because I drag the project from another folder and xcode finds troubles with permissions, or for some other (to me) unknown reasons.
Try to clean the project with alt+cmd+k . If that doesn't work you might have problems with permissions. So create another project and copy all the files you wrote to it.

It seems this was a stupid mistake by me, i got a rotationChanged notification too early, before i could process it. That caused a chain reaction which caused a crash in some obscure location. Thanks for the help anyway!

Related

subclass of UIViewController is unable to call loadView method

i have a subclass of UIViewController, and when it is called from another class the app just freezes - i used the Xcode debugger and figured that when I'm trying to access the class's view property the app freeze. another weird thing is that when i type in the debugger control panel: "po objectOfTheProblematicClass.view" the debugger stops responding.
the code I used was similar to this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
WTStickyViewController *stickyVC = [sb instantiateViewControllerWithIdentifier:#"WTStickyViewController"];
stickyVC.sticky = sticky;
// Setup view controller containment:
[self.parentViewController addChildViewController:stickyVC];
self.containerView = self.parentViewController.view;
[self.containerView addSubview:stickyVC.view];
WTStickyViewController is the subclass of UIViewController. the app freezes when it reaches
[self.containerView addSubview:stickyVC.view];
but it's because this is the first time that stickyVC.view is called.
if for example i would put somewhere in the code
UIView *viewForExample = stickyVC.view;
the app would freeze there.
the exact same app works fine when compiled on a device with iOS 8 but has this problem with iOS 9.
if anyone knows why is this happening and if there is a solution it will be great. thank you.
I was having a similar issue and it was absolutely maddening. The CPU went to around 100% in the resource monitor during debug as the app deadlocked. Printing to console or just generally accessing the view controller's view property caused this behavior. Ultimately, what 'fixed' it for me was removing it from the base localization file. I know that doesn't make sense, but I'll elaborate as best as I can.
I'm maintaining a legacy universal app that has 2 'main' storyboards called Main_iPhone and Main_iPad, which as you can probably guess are the loaded dynamically based on what device you're launching on. I noticed that only the iPhone nib view was deadlocking as described, and iPad was loading fine. The only thing I could tell as that the iPhone storyboard had localization enabled while the iPad storyboard had not. So here's the steps I took loosely to remove it from base localization (you may want to do this in a separate branch/sandbox to make sure this works before deleting project references):
Right click the problematic view and/or storyboard in question, show in finder. For me it was inside the Base.lproj folder as expected.
[Re]move the file to a different directory so Xcode can not find the link the project (file goes red in file browser). Press delete to remove the file from the project file's reference from the project itself.
Add the file back at the new location in your repository/project structure so Xcode picks it up as a new file. Ensure all of your references to the file are updated to the new location.
Verify your storyboard/xib file is not localized anymore, clean project, re-run and see if the issue is still there (see image).
You can also just update the file location using the update location button in the file properties view on the right side (see other image).
Don't know if this will fix it, but I thought I'd share what helped me in the chance that it helps others as well.
A bug report was sent to apple and hopefully it will be fixed soon - the problem is indeed with Xcode 7.
If you are encountering a similar problem, it can be solved by doing one of the following:
1) Use Xcode 6.4, at least until apple fixes this bug.
2) Rebuild the problematic view in the storyboard.
I will post the radar link once I got a chance to speak with my manager about it...

App crashing without errors

In my app, I have four buttons. When I press two of the four buttons, the app freezes. The weird thing is that no errors appear and there is nothing in the debugger window. I am new to iOS development, so I have no idea how to fix this. The app worked fine before the app started crashing, and I didn't alter any code, so I don't know what is going on. Can someone help me out?
Here is the code for where the button is pushed. It has been working fine, so I don't know why it doesn't work all of the sudden:
- (IBAction)showMapView:(id)sender
{
P2OViewController *pvc = [[P2OViewController alloc]init];
[self.navigationController pushViewController:pvc
animated:YES];
}
- (IBAction)showTableView:(id)sender
{
TableViewController *tableView = [[TableViewController alloc]init];
[self.navigationController pushViewController:tableView
animated:YES];
}
So I added global breakpoints, and nothing is happening. The app is still running, and the debugger navigator says it is still running. So I guess the app is freezing, and not crashing. I have no idea how to fix this.
Seems like a memory problem.Instead of creating a p20viewcontroller object and tableviewcontroller object on every button click,try creating these objects only once somewhere in the start of the program.
the button click should only contain the code to navigate to the next screen.Not creating a new object on every button click.
I'd suggest you check the connections between your IBActions and your code. Unexplained errors like this can be caused by missing or incorrect connections in IB.

Error loading .xib - application crash

I am banging my head against a brick wall. I am trying to push a view onto a UINavigationController in the usual manner:
[[self navigationController]pushViewController:vc animated:YES];
When I do this the app crashes with the following error:
__CFStringEncodeByteStream + 17
Thread 1: EXC_BAD_ACCESS (code=2,address=xxxxx)
Now, I have replaced the ViewController in question with a template provided by XCode and I do not get the error so the issue must be with my UIViewController class. Furthermore, if I replace the nib name with that of the template UIViewController class it works .i.e.
MyViewController *myVc = [[MyViewController alloc]initWithNibName:#"XCodeViewController" bundle:nil];
This leads me to think that the issue is actually with the nib and not the class itself. I have checked through all the connections and there are no errors or warnings.
Hopefully somebody can help.
Thanks
I was dealing with a very frustrating bug similar to yours, and everything was in place.
The newly created xib was added to the Bundle resources, no nil pointers or released pointer, NSZombieEnabled was set. The File's Owner was set to the correct ViewController as well
After sitting down with my senior for 30 minutes, we finally realized what was wrong -
In the newly created Xib, even after you assign the File's Owner to the ViewController there is an additional step which you need to take.
You need to have the main View's referencing Outlet set to the File's owner as well. The easiest way to do this is to Drag the "+" sign on the referencing outlet(From the Connections inspector) to the "File's Owner" in the Document Outline. After this you just need to click on "view" which pops up and you should be good.
Hope that helps you or anyone else facing the same problem
Need more info to answer, I can give few possibilities.
Check if the class name is mapped properly in your identity inspector.
And check your connections too. If your view is mapped in xib., etc.
If your running the app in OS below 6.0 & built with features such as Auto layout, it leads to crash.
There are multiple possibilities.
Hope this gives an insight.
Check if your nib is added to the application bundle. You can do that by selection you project file->Build Phases->Copy Bundle Resources.
If it is not there, add it.
I had the same issue yesterday and this was the problem.
I hope it helps.

dismissModalViewControllerAnimated mystery

I've seen a number of posts on this subject, but none that leave me with a clear understanding of what is happening.
I've set up a small test involving two UIViewControllers: MainController and ModalController.
MainController has a button on it that presents a modal view controller using the following simple code:
ModalController *myModal = [[ModalController alloc] init];
[self presentModalViewController:myModal animated:YES];
[myModal release];
Now, if I immediately dismiss this modal controller from within the same block of code, as per this next line:
[self dismissModalViewControllerAnimated: YES];
The modal view does not dismiss.
Following some suggestions on this site, I put the dismissModalViewControllerAnimated call in a separate method, which I then called with:
[self performSelector:#selector(delayedDismissal) withObject:nil
afterDelay:0.41];
This works - at least if I make the delay 0.41 or greater. .40 or less and it doesn't work.
At this point, I'm assuming I'm dealing here a run-loop that needs to catch up with itself, for lack of a better description. It's not very stable, unfortunately.
So, for the next test, I make the delayedDismissal do nothing - it only serves to provide a delay - and re-insert the dismissModalViewControllerAnimated call back in the original block, such that my code now looks like this:
ModalController *myModal = [[ModalController alloc] init];
[self presentModalViewController:myModal animated:YES];
[myModal release];
self performSelector:#selector(delayedDismissal) withObject:nil
afterDelay:0.41]; // to create the false delay
[self dismissModalViewControllerAnimated: YES];
...now the dismissModalViewControllerAnimated doesn't work again, no matter how long a delay I use.
So, what is happening here? I realize, like others, I can achieve my goal through assorted workarounds, including the use of a delegate, etc. But I really think it would be good for everyone who encounters this issue to walk away with a thorough understanding of both the problem and the proper solution for this scenario. Incidentally, one use case for this scenario is to present a loading screen modally where the user has no interaction with that screen; it's just being used to present information while blocking the user from taking actions.
The view is animating, thus as long as it is animating calling dismiss won't work.
Also in the second thing you tried, you are calling a "delay" but what you are actually doing is saying the following: "Ok, here is this cute method, can you execute that 0.41 seconds later? thanks, in the mean time, call this method.."
Dismissing a modal view controller should be done through the userinterface, by clicking a button, so why are you trying this in the first place?

Plugin objects in WebView getting destroyed?

Here's my situation:
I've written a simple web browser. Tabbed browsing was easy enough to get working once I wrapped my head around the concepts and figured how to perform operations on specific tabs. It works well and is pretty reliable under most circumstances.
A problem has plagued me, however, and I cannot figure out its cause.
Let's say I open a new tab and navigate to YouTube. I click on a video and the flash player loads. The video plays and all works fine. I now create another new tab and navigate to some site. The audio from the youtube player stops completely.
When I switch back to the youtube tab, the page will all still be there just as it was except the player has to reload completely, as if I had just reloaded the page. This seems to apply to other plugin types as well.
What's causing this?
Garbage collection is not enabled and as far as I know I'm creating the web views properly. Is there some silly, simple little thing that I missed somewhere along the line?
The - (void)setHostWindow:(NSWindow *)hostWindow method on WebView is probably what you're looking for.
I had the same problem with the flash in a WebView reloading whenever the syle mask of the enclosing window was changed. Wrapping the call to setStyleMask fixed the problem, as follows:
NSWindow *hostWindow = [[NSWindow alloc] init];
[self.webView setHostWindow:hostWindow];
[[self windowForSheet] setStyleMask:styleMask];
[self.webView setHostWindow:nil];
[hostWindow release];
The documentation for the method isn't stellar, but it does explicitly state a having a WebView inside a NSTabView as one of the use cases:
This method sets the receiver’s host window to hostWindow. Your application should only use this method if a web view is going to be removed from its window temporarily, and you want the web view to continue operating (for example, you don’t want to interrupt a load in progress). Since the receiver retains hostWindow, it is your responsibility to set the host window to nil before closing the window to avoid a retain loop.
For example, you might invoke this method if you attach a web view to an NSTabView object (as in a tabbed browser implementation). The NSTabView object takes views out of the window when they are not in the active tab, so you need to invoke this method before the web view is removed from its window. If you don't invoke this method, plug-ins will stop operating when the web view is removed from its window.
I had a similar problem but with a window with a webView that is closed and restored. Unfortunately the solution by #mlwelles did not solve the problem alone.
What did solve however is removing the webView from the window before it closes (proper "timing" is important). What I came up with is something like this:
id contentView;
id tmpHostWindow;
[window setDelegate:self];
- (BOOL)windowShouldClose:(NSNotification *)notification
{
// set temporary hostWindow on WebView and remove it from
// the closed window to prevent stopping flash plugin
// (windowWillClose would be better but that doesn't always work)
tmpHostWindow = [[NSWindow alloc] init];
[webView setHostWindow:tmpHostWindow];
[window setContentView:nil];
[contentView removeFromSuperview];
return TRUE;
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
// restore "hidden" webview
// (would be better to do it in applicationShouldHandleReopen
// but that seems to be too early (has no effect)
if ([window contentView] != contentView) {
[window setContentView:contentView];
[webView setHostWindow:nil];
tmpHostWindow = nil;
}
}