Dismiss UIViewController does not deallocate memory - ios

I have this code
-(void)didPressButton:(int)tag
{
// Preventivi?
if (tag == 0)
{
if (addPrev == nil)
addPrev = [[avvAddPreventivoViewController alloc] init];
addPrev.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addPrev];
navigationController.navigationBarHidden = NO;
[[navigationController navigationBar] setBarStyle:UIBarStyleBlack];
[self presentViewController:navigationController animated:YES completion:nil];
addPrev = nil;
}
}
When I show up the addPrev the memory increases, when show off the memory does not release.
When the addPrev dismiss it fires a protocol methos, didCancel. I intercept it and release addPrev:
-(void)didCancel
{
[self dismissViewControllerAnimated:YES completion:nil];
addPrev = nil;
}

Niling also the navigation controller improves drastically the memory allocation.
Also, be careful to deallocate what you can deallocate in the dealloc of the pushed controller.
-(void)didPressButton:(int)tag
{
// Preventivi?
if (tag == 0)
{
if (addPrev == nil)
addPrev = [[avvAddPreventivoViewController alloc] init];
addPrev.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addPrev];
navigationController.navigationBarHidden = NO;
[[navigationController navigationBar] setBarStyle:UIBarStyleBlack];
[self presentViewController:navigationController animated:YES completion:nil];
addPrev = nil;
navigationController = nil;
}
}

Related

Fix Warning: Attempt to present ViewController on NavigationController whose view is not in the window hierarchy

Currently, I have set up a log-in view for users of my app. Below is the code that presents this log-in view to the user:
// Handle how we present the view
if (self.notificationToProcess != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWNotificationsViewController *viewController = [[NotificationsViewController alloc] init];
viewController.initialDataID = self.notificationToProcess[#"Data"];
self.notificationToProcess = nil;
[self.navigationController pushViewController:viewController animated:YES];
}];
} else if (self.detailURL != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
WebViewController *wvc = [[WebViewController alloc] init];
wvc.URL = self.detailURL;
wvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:wvc animated:YES completion:nil];
self.detailURL = nil;
}];
} else {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
What I'm attempting to do now is display a web-view first if the user has just updated the app. Below is what this new code looks like:
// Handle how we present the view.
if (self.notificationToProcess != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWNotificationsViewController *viewController = [[SWNotificationsViewController alloc] init];
viewController.initialDataID = self.notificationToProcess[#"Data"];
self.notificationToProcess = nil;
[self.navigationController pushViewController:viewController animated:YES];
}];
} else if (self.detailURL != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWWebViewController *wvc = [[SWWebViewController alloc] init];
wvc.URL = self.detailURL;
wvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:wvc animated:YES completion:nil];
self.detailURL = nil;
}];
else if (![versionOfLastRun isEqual:currentVersion])
{
SWWebViewController *webViewController = [[SWWebViewController alloc] init];
NSString *url=#"http://someurl";
webViewController.URL = url;
webViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:webViewController animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"VersionOfLastRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else if (versionOfLastRun == nil){
// First start after installing the app
}
else {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
However, when I run the app, the web view is not displayed, I get a warning of:
Warning: Attempt to present ViewController on NavigationController whose view is not in the window hierarchy!
Can anyone help me diagnose the problem? Thank you!
Seems like your viewController is not in Navigation controller hierarchy. This means that your controller is not connected with navigation controller stack which should handle presented controllers.
The other thing that should help is setting your root view controller as follows:
self.window.rootViewController = self.ViewController;
EDIT: since you mention that you don't use storyboards, setting rootViewController should do the trick.
Try to set the window's rootViewController to the navigation controller after you initialize the navigation controller:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:mainController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = navController;
This is how I'm doing it without storyboards.
The problem was that I didn't call self.navigationController dismissViewControllerAnimated:YES completion:^
After correcting this (see listing below), my WebView was shown as expected.
else if (![versionOfLastRun isEqual:currentVersion])
{
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWWebViewController *webViewController = [[SWWebViewController alloc] init];
NSLog(#"%#", self.window.rootViewController);
NSString *url=#"http://devstatwatch.drbsystems.com/releases_mobile.php";
webViewController.URL = url;
webViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:webViewController animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"VersionOfLastRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}];
}

modalPresentationStyle from button click

I have a _exampleButton:
_exampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_exampleButton setBackgroundColor:[UIColor redColor]];
[_exampleButton addTarget:self action:#selector(certificatesButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_exampleButton];
and the action:
-(void)certificatesButtonTouched
{
if(!_certificatesWindow)
{
_certificatesWindow = [[AWCertificatesViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:_certificatesWindow];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navController animated:YES completion:nil];
[_certificatesWindow release];
}
else {
[_certificatesWindow.view removeFromSuperview];
[_certificatesWindow release];
_certificatesWindow = nil;
}
}
this presents the window in modal view controller from other class:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:#selector(cancel:)];
self.navigationItem.leftBarButtonItem = cancelItem;
UITableView *table = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
[self.view addSubview:table];
_tableFromButton = table;
}
- (void)cancel:(id)sender
{
[self.presentingViewController dismissViewControllerAnimated:YES
completion:nil];
}
but after clicking the Cancel button, the Modal view controller view disappears, but if I click the _exampleButton again once- it will not appear, so I have to click it twice to show the modal view controller again. What is the problem?
It does this because that is what your code tell it to do...
You dismiss the view controller in -(void)cancel:(id)sender but this will not result in the _certificatesWindow iVar becoming nil in your first view controller. So when you touch the exampleButton again it will execute the else clause and clean up the _certificatesWindow view controller.
You should either use delegation or a code block to have the first view controller dismiss the second or remove the if/else test from your certificatesButtonTouched. Another alternative is to modify this method so that if _certificatesWindow is not nil it is reused -
-(void)certificatesButtonTouched
{
if(!_certificatesWindow)
{
_certificatesWindow = [[AWCertificatesViewController alloc] init];
}
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:_certificatesWindow];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navController animated:YES completion:nil];
}
But this may or may not be desirable depending on what the second view controller shows.
I would also suggest you look at converting to ARC if possible
The problem is after you tap "Cancel", _certificatesWindow still exists when you tap on certificatesButtonTouched. It will go to the Else statement on the First tap to make _certificatesWindow = nil.
if _certificatesWindow is not needed when you tap cancel, you might want to do the following:-
- (void)cancel:(id)sender
{
[self.presentingViewController dismissViewControllerAnimated:YES
completion:nil];
[_certificatesWindow.view removeFromSuperview];
[_certificatesWindow release];
_certificatesWindow = nil;
}
allocate view like this in view did load method
if(!_certificatesWindow)
{
_certificatesWindow = [[ViewController1 alloc] init];
}
-(void)certificatesButtonTouched
{
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:_certificatesWindow];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navController animated:YES completion:nil];
}
replace your code with this
-(void)certificatesButtonTouched
{
if(!_certificatesWindow)
{
_certificatesWindow = [[AWCertificatesViewController alloc] init];
}
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:_certificatesWindow];
navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navController animated:YES completion:nil];
[_certificatesWindow release];
}

EKEventview controller not showing navigation bar

I used the following code to view the event. But navigation bar doesn't visible.
EKEventViewController *addController = [[EKEventViewController alloc] initWithNibName:nil bundle:nil];
addController.event = self.event;
addController.allowsEditing = YES;
addController.allowsCalendarPreview = YES;
[self.navigationController presentViewController:addController animated:YES completion:nil];
with Present viewcontroller you need to Add sepreated NavigationController for UIViewcontroller like:-
EKEventViewController *addController = [[EKEventViewController alloc] initWithNibName:#"EKEventViewController" bundle:nil];
UINavigationController *navController=[[UINavigationController alloc]initWithRootViewController:addController];
addController.event = self.event;
addController.allowsEditing = YES;
addController.allowsCalendarPreview = YES;
if ([self respondsToSelector:#selector(presentViewController:animated:completion:)])
{
[self presentViewController:navController animated:YES completion:nil];
}
else
{
[self presentModalViewController:navController animated:YES];
}

Unable to call Lock Screen view controller from AppDelegate

I have implemented the KKLockscreen view controller and is working well within the in-app settings controller. Able to set passcode and change them as well.
I am having problem to call he lock screen view from appdelegate. I have added delegate .h file and imported the view controller in .m file. still it's not calling the lockscreen. any help?
below is my code.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if ([[KKPasscodeLock sharedLock] isPasscodeRequired]) {
KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil bundle:nil];
vc.mode = KKPasscodeModeEnter;
vc.delegate = self;
dispatch_async(dispatch_get_main_queue(),^ {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
nav.modalPresentationStyle = UIModalPresentationFormSheet;
nav.navigationBar.barStyle = UIBarStyleBlack;
nav.navigationBar.opaque = NO;
} else {
nav.navigationBar.tintColor = _navigationController.navigationBar.tintColor;
nav.navigationBar.translucent = _navigationController.navigationBar.translucent;
nav.navigationBar.opaque = _navigationController.navigationBar.opaque;
nav.navigationBar.barStyle = _navigationController.navigationBar.barStyle;
}
[_navigationController presentModalViewController:nav animated:NO];
});
}
}
i have checked it with my code and it is working ,ya but you have not give nib name here in this line and i have given may be that why it is not displaying your view.
KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil bundle:nil]
-(void)applicationDidBecomeActive:(UIApplication *)application {
RootViewController *vc = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
dispatch_async(dispatch_get_main_queue(),^ {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
nav.modalPresentationStyle = UIModalPresentationFormSheet;
nav.navigationBar.barStyle = UIBarStyleBlack;
nav.navigationBar.opaque = NO;
} else {
nav.navigationBar.tintColor = navigationController.navigationBar.tintColor;
nav.navigationBar.translucent = navigationController.navigationBar.translucent;
nav.navigationBar.opaque = navigationController.navigationBar.opaque;
nav.navigationBar.barStyle = navigationController.navigationBar.barStyle;
}
[navigationController presentModalViewController:nav animated:NO];
});
}

changin modalPresentationStyle after rotaiting

I need help in problem. I want to change modalPresentationStyle dynamicaly when it open, after rotating event.
I write this for create modalView
ZUITableViewController *ivc = [[ZUITableViewController alloc] init];
ivc.delegate = self;
_modalIsShowing = TRUE;
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ivc];
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
{
nc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
nc.modalPresentationStyle = UIModalPresentationFormSheet;
}
else{
nc.modalPresentationStyle = UIModalPresentationFullScreen;
}
[self presentModalViewController:nc animated:YES];
[ivc release];
[nc release];
Scrap the if statement UIModalPresentationPageSheet behaves properly to start with.
ZUITableViewController *ivc = [[ZUITableViewController alloc] init];
ivc.delegate = self;
_modalIsShowing = TRUE;
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ivc];
nc.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController:nc animated:YES];
[ivc release];
[nc release];

Resources