I have to show one popOver inside the left side of one splitController, I initialize the popOver whit an navigationController. But when i show the popOver my app crash.
Impostazioni *settings = [[Impostazioni alloc] initWithStyle:UITableViewStyleGrouped];
settings.title = NSLocalizedString(#"SETTINGS", nil);
settings.contentSizeForViewInPopover = kContentSizeOfPopOver;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:settings];
nav.navigationBar.tintColor = kTintColorNavigationBar;
nav.contentSizeForViewInPopover = kContentSizeOfPopOver;
UIPopoverController *popOver = [[UIPopoverController alloc] initWithContentViewController:nav];
[popOver presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
This is my code. Any ideas?
EDIT: Crash even if I set only a viewController instead of SplitController :/ And with a empty ViewController :/
(Possibly duplicate of Error using UIPopoverController.)
In short, you need to retain the UIPopoverController somehow. Either by defining a property for it or by managing the ref count manually. With ARC, the latter is not an option, so you need to store the reference.
I believe you need an instance variable to hold the popoverController. Otherwise after the method that contains the code that you showed finishes nothing will have retained your popover. Unlike when you add a subview to a view which the view would then retain the subview. The same thing does not take place for popovers.
Related
The project currently has a UIviewController called "Dashboard" that acts as the main view of all the application. This main view consists of two subviews on top of it, kind of like a splitview. The left side of the main (left view) has multiple buttons. The right side (right view) will display the content of the selected button of the left.
When a button is pressed it will create a new instance of the view that is going to display like this :
vcMySchedule_iPad *vcSchedule = [[vcMySchedule_iPad alloc] initWithNibName:#"vcMySchedule_iPad" bundle:nil];
ncDashboard = [[UINavigationController alloc] initWithRootViewController:vcSchedule];
ncDashboard.navigationBar.barStyle = UIBarStyleBlackOpaque;
ncDashboard.view.frame = self.vwRightPanel.bounds;
[self.vwRightPanel addSubview:ncDashboard.view];
The thing is that when pressing another button it will display another view, but the memory of the previous one called still remains, and the dealloc of the previous view never gets called.
I'm not using a split view cause the left side has a button that when pressend it will move the left side to the left and the right side will move the the left to view completely.
Is there any approach to this?
Updated with some images...
Main (MainViewController):
Pressed Course Catalog:
vcCourseCatalog_iPad *vcCourse = [[vcCourseCatalog_iPad alloc] initWithNibName:#"vcCourseCatalog_iPad" bundle:nil];
ncDashboard = [[UINavigationController alloc] initWithRootViewController:vcCourse];
ncDashboard.navigationBar.barStyle = UIBarStyleBlackOpaque;
ncDashboard.view.frame = self.vwRightPanel.bounds;
[self.vwRightPanel addSubview:ncDashboard.view];
When selecting a row form the table it displays the detail and if the user press the button the view is displayed max.
I think I may have been calling the new views wrong perhaps. Where are the objects released?
Without more information, I can't give solid advice, but check the following:
Are you using ARC? If not, remember that you must explicitly release all references before something is dealloc'd.
Do you keep ahold of a reference to the subview anywhere else? If you are still referencing it somewhere (especially in ARC), it will stick around. Circular references are evil here.
Are you removing the subview from it's superview before you replace it with the new one? You'd be surprised how often it is something as simple as this.
EDIT:
In response to below, about you not using ARC, its plainly obvious that 1) is your problem. You are not releasing references. In this case, it seems quite obvious here:
vcCourseCatalog_iPad *vcCourse = [[vcCourseCatalog_iPad alloc] initWithNibName:#"vcCourseCatalog_iPad" bundle:nil]; ncDashboard = [[UINavigationController alloc] initWithRootViewController:vcCourse];
ncDashboard.navigationBar.barStyle = UIBarStyleBlackOpaque;
ncDashboard.view.frame = self.vwRightPanel.bounds;
[self.vwRightPanel addSubview:ncDashboard.view];
that you are allocating a vcCourseCatalog_iPad and a UINavigationController, without ever releasing them. Optimally, you'd autorelease the vcCourseCatalog_iPad, and release the navigation controller when you swap it out.
Your code ought to look something like this:
vcCourseCatalog_iPad *vcCourse = [[[vcCourseCatalog_iPad alloc] initWithNibName:#"vcCourseCatalog_iPad" bundle:nil] autorelease];
if(ncDashboard)
{
//do any sort of removal from views here
//[ncDashboard.view removeFromSuperview];
[ncDashboard release];
}
ncDashboard = [[UINavigationController alloc] initWithRootViewController:vcCourse];
ncDashboard.navigationBar.barStyle = UIBarStyleBlackOpaque;
ncDashboard.view.frame = self.vwRightPanel.bounds;
[self.vwRightPanel addSubview:ncDashboard.view];
Additionally to CrimsonDiego's answer, I'd suggest that you use followings lines in your files:
In the .h file:
#property (nonatomic, retain) UIView *ncDashBoard;
In the .m file:
#synthesize ncDashBoard = _ncDashBoard;
and then use _ncDashBoard only from then on. This is to make sure that the retain count is set properly.
I am having memory leaks when I m using a view controller's view
My code sequence is like this
viewController1 = [[ViewController alloc] init];
destinationViewController = [[DestinationViewController alloc] init];
[destinationViewCOntroller useView:viewController1.view];
[viewController1 release];
[destinationViewController release];
And for testing purpose I have empty implementation in useView method. So my problem is viewController1 is never getting deallocated. I have made sure that no other place has any reference to viewController1.
When I remove the method call(useView) where I pass viewcontroller1.view then viewcontroller1 is deallocating properly.
Any ideas why the behaviour is like this?
This seems to be a rather academic problem. Just enable ARC and forget about it.
Imagine that we have multiview apllication which is controlled by Navigation Controller. We go from the first view to second by using pushViewController method and that's not a problem but then we need to move to the third view. And the third one is a view which looks like a TabBar. How do we do that? The third view is supposed to be controlled by TabBarController, isn't it?
So how to pass the control? I declared an outlet UITabBarController * tbc and connected it to TabBarController in xib file and then i tried this in viewDidLoad:
tbc = [[UITabBarController alloc]init];
and it shows nothing.
Your help is highly appreciated
It's a bit wierd. Its more standard to have a tabBarController that switches views and some of those views may be navigation controllers. But ...
Create the UITabBarController and push it.
NSMutableArray *viewControllers = [[NSMutableArray alloc] init];
// create someView
[viewControllers addObject:someView];
// create someView2
[viewControllers addObject:someView2];
UITabBarController *tabController = [[UITabBarController alloc] init];
[tabController setViewControllers:viewControllers];
[[self navigationController] pushViewController:tabController animated:YES];
Then, from the tabBarContoller view, based on some action, you can choose to pop it:
[self.navigationController popViewControllerAnimated: NO];
You can wire it up in the storyboard editor in the latest version of Xcode.
However, since this is very much non-standard use of the controls, you would need a very good reason as to why you would want a UI like this.
And even then, Apple's review process might turn your app down if the interface is clunky.
Any help is appreciated ! It's several days I'm fighting w/o results.
The scenario:
I and iPad application have a SplitViewController that shows 2 controllersViews (Root on the left e Detail on the right)
The Root allows a recursive navigation (tree that could be several drilldown levels) and I'm calling every time the same controller class (UITableView) pushing always in the controller stack). When the user taps a cell (left side), the detail view (right side) shows the information.
Keep in mind that the detail view controller is not always the same class: it means that I'm allocating (and releasing) programmatically several detailView controllers according the kind of information I have to display.
Here the fragment:
UIViewController <ItemGenericViewController> *newDetailViewController = [[NSClassFromString(cntrClass) alloc] initWithNibName:cntrXib bundle:nil];
//the detailViewController has been defined in the head section as ItemGenericViewController
//each detailViewController is a subclass of ItemGenericViewController
detailViewController = newDetailViewController;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:detailViewController];
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, nav, nil];
self.splitViewController.viewControllers = viewControllers;
[nav release];
[viewControllers release];
[detailViewController release];
Everything is working fine until a memory warning arises.
From that moment if I try to display a new detailViewcontroller the "connection" in the SplitViewController, between the RootController and the detailController, seems vanished. The result is: nothing appear on the right part of the splitController.
In the mean time if I navigate to parent level in the root controller the situation still failing.
For your information each time I push in the stack a new RootController instance (left column) I'm releasing the same controller (to save memory as usual) and I suspect, after receiving the memory warning, iOS is trying to free itself memory and my "history" disappear and the related connection, throught the split controller, too.
Is a nightmare ;-)
Do you have any suggestion ?
Thanks
Dario
I had a similar problem to you (maybe even worse - 16 combinations of possible view switches)... But I believe i have solved it right now.
So, i believe you have used Apple's example for view switching (I have, with modifications), and if you have so, problem is that "root" splitViewController (from MainWindow.xib) get's "niled" as default behavior when memory warning. And even if you add new array of view controllers to it, it will not cause any change (and even worse, it will not show any sign of warning). And solution is to check is it nil, and if is, to reinitialize it.
here is the code, using example from above:
UIViewController <ItemGenericViewController> *newDetailViewController = [[NSClassFromString(cntrClass) alloc] initWithNibName:cntrXib bundle:nil];
//the detailViewController has been defined in the head section as ItemGenericViewController
//each detailViewController is a subclass of ItemGenericViewController
detailViewController = newDetailViewController;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:detailViewController];
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, nav, nil];
/**** Milos Edit ****/
if (self.splitViewController == nil) {
// I'm keeping reference in app delegate, but any way to reinitialize splitViewController is OK
self.splitViewController = delegate.splitViewController;
}
/**** end of edit ****/
self.splitViewController.viewControllers = viewControllers;
[nav release];
[viewControllers release];
[detailViewController release];
Hope it will be helpful.
Cheers
Milos
I'm having a problem with an iPhone App using UINavigationController. When I'm using pushNavigationController, it works fine. The iPhone does its animation while switching to the next ViewController. But when using an array of ViewControllers and the setViewControllers method, it has a glitch in the animation which can grow into a clearly visible animation bug.
The following snippet is called in the root ViewController. Depending on a condition it should either switch to ViewController1, or it should directly go to ViewController2. In the latter case the user can navigate back to vc1, then to the root.
NSMutableArray* viewControllers = [NSMutableArray arrayWithCapacity:2];
// put us on the stack
[viewControllers addObject:self];
// add first VC
AuthentificationViewController* authentificationViewController =
[[[AuthentificationViewController alloc] initWithNibName:#"AuthentificationViewController" bundle:nil] autorelease];
[viewControllers addObject:authentificationViewController];
if (someCondition == YES)
{
UserAssignmentsListViewController* userAssignmentsListViewController =
[[[UserAssignmentsListViewController alloc] initWithNibName:#"UserAssignmentsOverviewViewController" bundle:nil] autorelease];
[viewControllers addObject:userAssignmentsListViewController];
}
[self.navigationController
setViewControllers:[NSArray arrayWithArray:viewControllers] animated:YES];
As you can see I'll add the first and maybe the second VC to the array, finally setting the navigationController stack with animation. This works properly if I only add the first controller. But in the case where the animation should go to the 2nd controller, the navigation bar's title won't be "flying in". Instead there is an empty title until the animation is finished. And, even worse, if I replace the navbar title with a custom button, this button will be displayed in the upper left corner until the animation is finished. That's quite a displaying bug.
I tried to use a workaround with multiple pushViewController methods, but the animation doesn't look / feel right. I want the navigation to do its animation in the same way as pushViewController does. The only difference here is, that I don't add a VC but set the whole stack at once. Is there another workaround here, or could this be considered as a framework's bug? I thought about using only pushNavController for VC2, then somehow insert VC1 into the stack, but that doesn't seem possible.
Thanks for all hints and advices. :-)
Technical data: I'm using iOS 4.2, compiling for 4.0.
Finally I found the solution. The mistake was that the new top-level NavigationController has not been initialized and loaded properly until the animation is done. In my case, UserAssignmentsListViewController has a viewDidLoad method that will not be called until animation is done, but it sets the navigation title (here: a UIButton). Therefore the animation fails.
The solution is to refer to an already initialized view controller when it comes to pushing it to the stack. So initialize our top-level VC somewhere:
// initialize our top-level controller
ViewController* viewController2 = [[[ViewController alloc]
initWithNibName:#"ViewController" bundle:nil] autorelease];
Then when pushing two or more VCs to the stack, the top level one is already initialized and the animation works (following the example from my original question):
NSMutableArray* viewControllers = [NSMutableArray arrayWithCapacity:2];
// put us on the stack, too
[viewControllers addObject:self];
ViewController* viewController1 = [[[ViewController alloc]
initWithNibName:#"ViewController" bundle:nil] autorelease];
[viewControllers addObject:viewController1];
if (someCondition == YES)
{
[viewControllers addObject:viewController2];
}
[self.navigationController
setViewControllers:[NSArray arrayWithArray:viewControllers] animated:YES];