I am using the following code in my view controller and I want it to present another view controller called "chooserViewController" modaly
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
[self presentModalViewController:chooserViewController animated:YES];
}
I am getting a compile error not recognizing "chooserViewController". Am I doing it wrong?
Update:
- (void)add:(id)sender
{
RoutineExerciseChooserViewController *routineExerciseChooserViewController = [[RoutineExerciseChooserViewController alloc] initWithNibName:#"RoutineExerciseChooserViewController" bundle: nil];
[self presentModalViewController:routineExerciseChooserViewController animated:YES];
[routineExerciseChooserViewController release];
}
You need to create chooserViewController:
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated {
ChooserViewController *chooserViewController = [[ChooserViewController alloc] initWithNibName:#"ChooserView" bundle: nil];
[self presentModalViewController:chooserViewController animated:YES];
[chooserViewController release];
}
If you're not loading from a nib, obviously you'll use a different way to create chooserViewController, but you have to do something to ensure it exists, and can then be presented.
Related
I have a MBProgressHUD that I want to display when switching tabs. This is in my app delegate. I have this code here to display the HUD on only the first three tabs
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
if ([viewController isKindOfClass:[UINavigationController class]]) {
if (tabBarController.selectedIndex >= 3) {
UINavigationController *nav = (UINavigationController *) viewController;
[nav popToRootViewControllerAnimated:NO];
}
else {
UINavigationController *nav = (UINavigationController *) viewController;
HUD = [[MBProgressHUD alloc] initWithView:nav.view];
[nav.view addSubview:HUD];
HUD.labelText = #"Loading";
[HUD show:YES];
[nav popToRootViewControllerAnimated:NO];
}
}
}
The first time I view my page it works but going back to it a second time it doesn't hide. I have my [appDel.HUD hide:YES afterDelay:1.0]; in my viewDidAppear.
How can I get the HUD to hide every time I visit the page?
I think you may be adding the MBProgressHUD to a different view within the UINavigationController. Then you're popping to the root, and it's trying to remove an MBProgressHUD that doesn't exist. Try this (untested code)...
UINavigationController *nav = (UINavigationController *) viewController;
[nav popToRootViewControllerAnimated:NO];
if(![nav.visibleViewController.view.subViews containsObject:MBProgressHUD])
{
[MBProgressHUD showHUDAddedTo:nav.visibleViewController.view animated:YES];
MBProgressHUD.labelText = #"Loading";
}
else
{
[MBProgressHUD setHidden:NO];
}
you have to check if the MBProgressHUD view was already activated if so hid it, or simply do so:
if (!HUD) {
[self showLoadingHUD];
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
ChatViewController *chatView;
if(contactView==nil)
{
chatView=[[ChatViewController alloc] initWithNibName:#"ChatViewController" bundle:nil];
}
[self.navigationController pushViewController:chatView animated:YES];
[messageDelegate newMessageReceived:m];
}
The above delegate method called for every incoming message.When it called, it goes to a new UIViewController.Here my problem is a view pushed multiple tinmes,so error will be occered.how can i fix this error in iphone
Add this snippet before pushing the view controller
BOOL viewControllerAlreadyPushed = NO;
for (UIViewController *controller in self.navigationController.viewControllers) {
if ([controller isKindOfClass:[ChatViewController class]]) {
viewControllerAlreadyPushed = YES;
}
}
if(!viewControllerAlreadyPushed) //if not pushed, push it
{
ChatViewController *chatView;
if(contactView==nil)
{
chatView=[[ChatViewController alloc] initWithNibName:#"ChatViewController" bundle:nil];
}
[self.navigationController pushViewController:chatView animated:YES];
[messageDelegate newMessageReceived:m];
}
My iPhone app badly leaks when flipping back and forth between a main uiviewcontroller and a help uiviewcontroller .
Here is the source of the main view, followed by source of the help view.
MAIN VIEW - FLIP TO HELP.....................
// Changes from operational view to Help view.
- (IBAction)showHelp:(id)sender
{
// End trial mode:
self.stop_trial_if_started;
self.rename_trial_if_edited;
// Switch to trial help:
help_view_context = 0;
HelpView *controller = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
HELP VIEW - INIT.............................
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
help_scroll.editable = FALSE;
return;
}
HELP - RETURN TO MAIN VIEW.........................
// User clicked the button to return to operational view:
- (IBAction)done:(id)sender {
NSLog(#"help- done");
if( help_view_context == 0 ) {
[self.delegate trial_help_DidFinish:self];
}else{
[self.delegate file_help_DidFinish:self];
}
}
MAIN VIEW - RETURN FROM HELP...............................
// Inits operational view when user changes from Help view back to operational view.
- (void)trial_help_DidFinish:(HelpView *)controller {
NSLog(#"trial_help_DidFinish");
[self dismissModalViewControllerAnimated:YES];
self.init_trial_operation;
}
You are creating a controller with ref count of 1 and a local reference each time showHelp: is called:
HelpView *controller = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
you are losing your reference to it at the end of this method.
You happen to have references to it in done: (self) and *_help_didFinish (controller), but you never release it in either of those locations. Dismissing the controller is fine, but you also have to release it.
(Another option would be to never create a second one, and maintain an iVar to the original.)
You could well be leaking on this line
controller.delegate = self;
What is your property declaration for the delegate. If it's anything other than assign, then you either need to change it (preferred option) or make sure you are releasing it in the dealloc method of HelpView controller.
here the following code is used to view the present modal view controller.
[[self navigationController] presentModalViewController:doctorListViewNavigationController animated:YES];
the close action is in the next view controller(DoctorListViewController). You can understand by seeing the following code I added now cleary.
-(void)doctorsListAction
{
if(isFirst == YES)
{
[self getDoctorsListController];
[[self navigationController] presentModalViewController:doctorListViewNavigationController animated:YES];
}
}
-(void)getDoctorsListController
{
DoctorListViewController *doctorListViewController=[[DoctorListViewController alloc]init];
doctorListViewController.doctorList=doctorList;
doctorListViewNavigationController=[[UINavigationController alloc]initWithRootViewController:doctorListViewController];
doctorListViewNavigationController.navigationBar.barStyle= UIBarStyleBlackOpaque;
[doctorListViewController release];
//code in next DoctorListViewContrller to dismiss the view.
//code for dismiss the ModalViewController.
-(void)closeAction
{
[[self navigationController] dismissModalViewControllerAnimated:YES];
}
My problem is the dealloc method is not called then I am getting memory issue problems like object allocations, leaks..
- (void)dealloc
{
[doctorList release];
[myTableView release];
[super dealloc];
}
Dealloc method is called when object is released same number of times, as it was retained.
When you add doctorListView... (let's call it view) to navigationController (let's call it controller), the controller retains the view. And it was also retained during creation. That's why you should release this view twice: one time with dismissModalView... and one with direct release.
I mean something like this:
[[self navigationController] presentModalViewController:doctorListViewNavigationController animated:YES];
[doctorListViewNavigationController release]; // first time
...
- (void)closeAction {
[[self navigationController] dismissModalViewControllerAnimated:YES];
// second time
}
I have a MKMapView (also a UIPopoverControllerDelegate) with Annotations. This MapView has, in the MKTestMapView.h file, a UIPopoverController* popoverController defined in the #interface and a #property (nonatomic, retain) UIPopoverController* popoverController; defined outside of the #interface section. This controller is #synthesized in the MKTestMapView.m file and it is released in the - (void)dealloc section. The Annotations in this MapView have rightCalloutAccessoryViews defined to the following:
- (void)mapView:(MKMapView *)mapView2 annotationView:(MKAnnotationView *)aview calloutAccessoryControlTapped:(UIControl *)control{
...
CGPoint leftTopPoint = [mapView2 convertCoordinate:aview.annotation.coordinate toPointToView:mapView2];
int boxDY=leftTopPoint.y;
int boxDX=leftTopPoint.x;
NSLog(#"\nDX:%d,DY:%d\n",boxDX,boxDY);
popoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
popoverController.delegate = self;
CGSize maximumLabelSize = CGSizeMake(320.0f,600.0f);
popoverController.popoverContentSize = maximumLabelSize;
CGRect rect = CGRectMake(boxDX, boxDY, 320.0f, 600.0f);
[popoverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
...
}
Now here comes the fun part. First of all, I am not sure if I need maximumLabelSize and the rect to be the same size. I am new to the popovercontroller so I am playing this by ear..
Okay, the popover shows. Now to dismissing it. I can click anywhere on mapView2 and the popover goes away...but I need the user to click a button in the view if they change anything. URGH!
The docs show:
To dismiss a popover programmatically,
call the dismissPopoverAnimated:
method of the popover controller.
Well, here is the problem: By definition of how the popoverController works, you are clicking inside the view of the displayed popover (to click the button) but have to trigger the dismissPopoverAnimated: method of the controller that launched this popover view, in my case, the popoverController inside the MKTestMapView.m file.
Now, having said all that, remember, [popoverController release] doesn't happen until:
- (void)dealloc {
[popoverController release];
[mapView release];
[super dealloc];
}
So, do i just do the following inside the button (messy but may work):
(Assuming my popover view is a TableView) In the:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MKTestMapView * mKTestMapView = [[MKTestMapView alloc] init];
[[mKTestMapView popoverController].dismissPopoverAnimated:YES];
}
Here is my issue: I cannot figure out whether doing the above gives me a reference (if there is such a thing) to the existing view that is on the screen -- and therefore the view that is the owner of that popoverController. If it is as simple as
[[[self parentView] popoverController].dismissPopoverAnimated:YES];
I will shoot myself cos I don't think that is the correct syntax either!
This should be easy...yet I am lost. (probably just frustrated with so many iPad differences that I am learning).
Can anyone explain more?
I had the same problem... I had a neat "close" button (X) in the top of my view loaded by the popover, but it didn't work. In my universal app it will be presented as a new view, so that code should stay.
What I did now was that I added the following to my detailedPinView (the view the popover loads):
in the detailedPinView.h file:
#interface detailedPinView : UIViewController {
[...]
UIPopoverController *popover;
[...]
}
-(void)setPopover:(UIPopoverController*)aPopover;
In the detailedPinView.m file:
- (void)setPopover:(UIPopoverController*)aPopover
{
popover = aPopover;
}
The X button closes the view using an IBAction, this is what I did there:
In the detailedPinView.m file:
-(IBAction)releaseDetailedView:(UIButton *)sender
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
if (popover != nil)
{
[popover dismissPopoverAnimated:YES];
}
else {
NSLog(#"Nothing to dismiss");
}
}
else{
[self.parentViewController dismissModalViewControllerAnimated: YES];
}
}
In the class loading the my map and the popover view I added the following code:
[...]
-(void)mapView:(MKMapView *)theMapView annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control
{
UIViewController *detailController = [[detailedPinView alloc] initWithNibName:#"detailedPinView"
bundle:nil
annotationView:pin];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
UIPopoverController* aPopover = [[UIPopoverController alloc] initWithContentViewController:detailController];
[aPopover setDelegate:self];
[aPopover setPopoverContentSize:CGSizeMake(320, 320) animated:YES];
[detailController setPopover:aPopover];
[detailController release];
[mapView deselectAnnotation:pin.annotation animated:YES];
self.popoverController = aPopover;
[mapView setCenterCoordinate:pin.annotation.coordinate animated:YES];
[self.popoverController presentPopoverFromRect:CGRectMake(382,498,0,0) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
else
{
[self presentModalViewController: detailController animated:YES];
}
[detailController release];
}
[...]
I don't know if the was the answer you were hoping for, I think it might be a bit of a messy way to do it... but giving the time schedule this worked like a charm :)
Here is another simple solution.
I found that we should follow the following steps for clearly dismissing popovers.
dismiss a popover.
release a view loaded by the popover.
Before iOS8, almost all of us may release a view loaded by a popover first, and then we programmatically dismiss the popover.
However, in iOS8, we do the steps in revers.
Before iOS8, my code of dismissing a popover
// creating a popover loading an image picker
picker = [[UIImagePickerController alloc] init];
...
pickerPopover = [[UIPopoverController alloc] initWithContentViewController:picker];
[pickerPopover presentPopoverFromRect:aFrame inView:aView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// dismissing the popover
[picker.view removeFromSuperview]; // (1) release a view loaded by a popover
[picker release], picker = nil;
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
[pickerPopover dismissPopoverAnimated:YES]; // (2) dismiss the popover
}
In iOS8, the dismissing code part should be changed as below,
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
[pickerPopover dismissPopoverAnimated:YES]; // (2) dismiss the popover first
}
[picker.view removeFromSuperview]; // (1) and then release the view loaded by the popover
[picker release], picker = nil;