Okay, so I have just started iOS development. I'll start by explaining the flow of my app :
1. A view called "appViewController" is loaded.
2. [self presentViewController: controller animated: YES completion:nil]; this loads a webview
3. After I am done with the webview, I dismiss it and load a new UINavigation this way :
[self dismissViewControllerAnimated:YES completion:^{
formViewController *fv = [ [formViewController alloc] init ];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:fv] autorelease];
navController.navigationBar.hidden = YES;
[presentingViewController presentModalViewController:navController animated:YES];
}];
5.The formViewController has a button, which has the event attached to it for that display an alert this way
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:#"test"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
Everything works as intended up till here. Now when I click the "Ok"(Cancel) button, the app crashes with NSZombieEnabled saying
-[appViewController _deepestDefaultFirstResponder]: message sent to deallocated instance 0x6e6a570 lldb
What is happening here? Why is it trying to send message to appViewController again? There is no code after [av show]
NOTE : I am using ARC
If you're using arc, the autorelease in your code isn't valid.
This seems like your root view controller gets deallocated at some point and when the responder chain gets traversed the resulting dangling pointer gets accessed.
To verify this, I would implement the dealloc method on appViewController and see if it gets called.
dealloc {
NSLog(#"Problems ahead.");
}
If this does get called before you'd expect that to happen (for a root view controller probably not at all), you need to find out why this happens. You're probably missing a strong reference somewhere. Check you app delegate and verify that you have a strong reference to the window and that you are setting your controller as the root view controller (provided you're not using storyboards).
The Zombies instrument is very good for debugging such problems. It will list all retains and releases of your problematic object. Here's a short introduction to it.
A couple of things.
You are mixing presentViewController and presentModalViewController. If you are new to iOS, you should always use presentViewController. No need getting used to using a method that will soon be deprecated (see answer to this question Difference between presentModalViewController and presentViewController?
In general, you shouldn't autorelease unless you absolutely have to. Since when a controller is presented with presentViewController (and presentModalViewController), it is retained, you can readily release afterwards. I would restructure like so:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:fv];
navController.navigationBar.hidden = YES;
[presentingViewController presentModalViewController:navController animated:YES];
[navController release];
3.. Where is the section of code you included located? Like, you push a button and the view is dismissed or what?
Related
dismissViewController method not working to get previous viewcontoller
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
popViewController work and go to previous viewcontroller
[self.navigationController popViewControllerAnimated:YES];
i want to pass data like below please help me.but as i describe dismissViewController method not working.
[self.navigationController dismissViewControllerAnimated:YES completion:^{
HomeVC *loading;
loading.IdNameLabel.text=display;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Code" message:display delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}];
thank in advance.
Update
-(void)viewWillAppear:(BOOL)animated{
self.IdNameLabel.text=self.GetscanResult;
}
this method contain in HomeVC.when dismiss navcontroller it shows HomeVC.
is upper method can call after dismiss viewcontroller?
SOLUTION
this is very stupid question when i am at beginner level.
here is specification about it.
it will depend on method which will you Present || Push viewController.
Delegate methods will work with protocol delegate method when view controller present.
The method you need to use to go back depends on how you showed the view controller.
The first of the two common ways are by using a navigation view controller to push and pop view controllers off the stack.
The other common way is to present and dismiss a view controller modally.
You cannot for example present a view controller modally, and expect to be able to pop it off from the navigation controller, or vice versa.
Warning: Attempt to present on whose view is not in the window hierarchy!
Yes I have looked at the other questions and answers before posting this question. They have not helped me resolve this. Here's what I am doing. I am calling on my singleton class socialHelper to display an action sheet, where postToFacebook method is an option to select. When clicking on this action, I get the Warning above and the postToFacebook is not displayed. I'm calling this from a UIViewController with the UINavigationController as the main controller, and my SocialHelper class is a NSOject.
- (void)postToFacebook
{
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
slComposeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[slComposeViewController setInitialText:#"Building stairs? Checkout StairsPro on the app store!"];
[slComposeViewController addImage:[UIImage imageNamed:#"StairsIcon120x120.png"]];
[slComposeViewController addURL:[NSURL URLWithString:#"https://itunes.apple.com/us/app/stairs-pro/id477032819?ls=1&mt=8"]];
[self presentViewController:slComposeViewController animated:YES completion:nil];
// I've also tried this, which shows the post window, but after hitting cancel or post, my previous viewController is not the current viewController. So my navigation bar is gone and can't move around in my app.
// [[[[UIApplication sharedApplication]delegate]window]setRootViewController:slComposeViewController];
}else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"No Facebook Account" message:#"No Facebook account has been configured. You can configure or create a Facebook account in settings." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
}
So what I'm asking is what is the best way to get the slComposerViewController to display in this case, also how we could use the UIApplication option as well. Thank you!
I would change the method to pass in the ViewController to make sure the correct VC is presenting it like so:
- (void)postToFacebookFromVC:(UIViewController*) presentingVC
And inside that method when calling presentViewController use:
[presentingVC presentViewController:slComposeViewController animated:YES completion:nil];
I assume then that using your socialHelper singleton class would be something like:
[[socialHelper sharedResource] postToFacebookFromVC:self]; //inside the VC that you want to display it
For your second question on using the rootViewController try this:
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:slComposeViewController animated:YES completion:nil];
Edit: Since the first two suggestions didn't work for your project, try getting the topMost ViewController and presenting slComposeViewController from it instead of "self" like so:
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
[topController presentViewController:slComposeViewController animated:YES completion:nil];
This answer won't resolve your issue but it should make some sense of why it isn't working and help you towards finding the right solution for what you originally intended.
SLComposeViewController being a UIViewController has an associated UIView that will be displayed on top of the view of the controller receiving the message presentViewController.
As correctly done in this line but, self needs to be a UIViewController (an object that has a view property).
[self presentViewController:slComposeViewController animated:YES completion:nil];
It will work if you move your -postToFaceBook method out of the SocialHelper class and put it inside your UIViewController class (file) that will display the action sheet, so that way self is actually a UIViewController instead of NSObject.
From Apple's UIViewController reference page:
When you call the presentViewController method on a UIViewController
it sets the presentedViewController property to the specified view
controller, resizes that view controller’s view and then adds the
view to the view hierarchy.
Your SocialHelper class is not a view controller so it does not have a view to which the action sheet view could be added to display it (on top).
I'm thinking even if you inherit your SocialHelper from UIViewController, the view of your SocialHelper would not be in your controller's view hierarchy.
If it is only two or three view controllers where you need to display the action sheet, I would replicate the code instead of creating a separate class; if it is several view controllers, then it makes sense to have the action sheet display logic as a separate class, you just need to find the right design pattern to do that.
Edit 1
Forgot to mention the declaration of your variable is missing the SLComposeViewController *
Is it just missing in your post or you have declared the variable somewhere else in your viewcontroller class?
Try declaring it right there in the same line you create the SLComposeViewController; that might fix the issue. If that did not work then double-check all you need to do to support Facebook in your app by looking at this very simple and easy to follow tutorial.
SLComposeViewController *slComposeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
I'm assuming you created your navigation controller with main view controller as its root:
navigationController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
And to show the flip side controller you do this in your main view controller:
[[self navigationController] pushViewController:flipSideViewController animated:NO];
The flip side controller has the about button to show the about view when tapped; I'm thinking you do a presentViewController not a push:
[self presentViewController:aboutViewController animated:YES];
Finally, in the about view controller you should have your -postToFacebook method with the corrected line mentioned above; which will be called by the log (button?).
I'm really stumped here.
_vc = [[VLCKitViewControlleriPhone alloc]initWithNibName:#"VLCKitViewControlleriPhone" bundle:nil];
_vc.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:_vc animated:YES completion:nil];
Gives me EXC_BAD_ACCESS (code = 2, address = 0x0) when the presentViewController method is called. The view controller is NOT nil. It also happens with or without a nib name. If I comment out the presentViewController line, the rest of the code continues fine, including method calls made to the view controller itself. The view controller is running, I just can't see anything because it's not actually showing the view.
I enabled NSZombies and tried it with Instruments running, but it's not showing me anything. The app just quits and instruments stops without giving me any information. Anyone know what the problem might be?
You can try this
if ([controller respondsToSelector:#selector(setModalPresentationStyle:)])
{
[controller setModalPresentationStyle:UIModalPresentationFullScreen];
} else {
[controller setModalPresentationStyle:UIModalPresentationFormSheet];
}
I have a UIViewcontroller that I want to push onto a UINavigationController, which in turn would push onto a modal view using presentModalViewController:animated.
Here's my code:
TargetViewController *targetViewController = [[[TargetViewController alloc] init] autorelease];
UINavigationController *targetNavController = [[[UINavigationController alloc] initWithRootViewController:targetViewController] autorelease];
[self presentModalViewController:targetNavController animated:YES];
When code is run, the modal view loads as expected, but after dismissModalViewControllerAnimated: is called, the modal view slides down and the app crashes.
I get the following error in gdb:
-[CALayer retain]: message sent to deallocated instance
First part of question: is there anything inherently wrong with the above code?
Second part: if there is nothing wrong with above code, where should I look next to debug?
Additional info:
When I don't release or autorelease the navController, it works fine. But Instruments will show abandoned memory, which I can only assume is the navController not being released. Maybe the modal view controller
P.S. I know that the crash is related to the memory management of the above ViewController, navController and modal view, because my code was working prior to messing with this code.
You generally don't push a navController as a view as the navigation controller works as the root controller. The views are pushed from the navController. Once you have a view pushed, you could then present the next view modally.
What happens if you don't use autorelease?
I.E.:
TargetViewController *targetViewController = [[TargetViewController alloc] init];
UINavigationController *targetNavController = [[UINavigationController alloc] initWithRootViewController:targetViewController];
[targetViewController release];
[self presentModalViewController:targetNavController animated:YES];
[targetNavController release];
Fixed the issue. I was releasing the VC, causing the crash. Thanks for the input.
-(void)showsearch:(id)sender
{
SearchViewController *searchview =[[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
settingpopoverController = [[[UIPopoverController alloc]
initWithContentViewController:searchview] autorelease];
[searchview release];
[settingpopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
When I click on button, the app is crash and I got [UIPopoverController dealloc] reached while popover is still visible. message.
There are some good discussions on this topic here:
Retain/release pattern for UIPopoverController, UIActionSheet, and modal view controllers?
UIPopoverController and memory management
The gist of it is you need to:
assign your autoreleased popover to a retain property
set the property to nil in your view's dealloc
as well as setting it to nil in the popoverControllerDidDismissPopover.
think autorelease is incorrect, here is a tutorial
http://www.jannisnikoy.nl/index.php/2010/04/ipad-tutorial-creating-a-popoverviewcontroller
Problem is you're setting
settingpopoverController =
when you mean to do
self.settingpopoverController =
for which the autorelease would be correct. The second one uses the property accessors, the first just uses the iVar.