Dismissing UIPopoverController with -dismissPopoverAnimated: won't call delegate? - iphone

I have my UIPopoverController with self as a delegate:
I receive calls when I tap outside the popover controller, but when I tap inside I want to dismiss too, so I use -dismissPopoverAnimated: but delegate is not called in this case.
Is this normal? Is this a bug or I am doing something wrong?
newDocPopoverController = [[UIPopoverController alloc] initWithContentViewController:vc];
[newDocPopoverController setPopoverContentSize:CGSizeMake(240, 44*4)];
[newDocPopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
[newDocPopoverController setDelegate:self];
UPDATE:
Oh, regardless the origin of the problem (Whether is a bug or this is the intended behavior) calling the delegate by myself solves the problem :)
When the contentViewController's view is touched I will call parent UIPopoverController's delegate a call.
if ([parentPopoverController.delegate popoverControllerShouldDismissPopover:parentPopoverController]){
[parentPopoverController dismissPopoverAnimated:YES];
[parentPopoverController.delegate popoverControllerDidDismissPopover:parentPopoverController];
}r];

That's normal, expected behavior.
Quoting the Apple docs on popoverControllerDidDismissPopover::
The popover controller does not call this method in response to programmatic calls to the dismissPopoverAnimated: method. If you dismiss the popover programmatically, you should perform any cleanup actions immediately after calling the dismissPopoverAnimated: method.

Programmatically the popoverControllerDidDismissPopover does not get called and won't dismissed, you'll have to call the delegate yourself:
[self.PopUp dismissPopoverAnimated:YES];
[self.PopUp.delegate popoverControllerDidDismissPopover:self.PopUp];
Where PopUp is the parent UIPopoverController
Hope this helps
Cheers
Al

set the delegate first;
yourPopup.delegate=self;
then some where in your code (May be in Particular Method call due some event).
use the following code;
[self.yourPopUp dismissPopoverAnimated:YES];

Related

Presenting a ModalViewController inside a ModalViewController

I have a view which is presented as a modal view controller which takes username and password credentials. I want this view to check the delegate, and if the user hasn't previously set an unlock pin for the app, to then show the change pin view as a modal view controller. This is my code...
+(void)presentCredentialsViewController:(UIViewController *)vc{
CredentialsViewController *cvc = [[CredentialsViewController alloc] init];
[vc presentModalViewController:cvc animated:FALSE];
}
and then in CredentialsViewController
-(void)viewDidLoad{
[super viewDidLoad];
if([appDelegate.pin isEqualToString: #""]){
UserPrefsViewController *upvc = [[UserPrefsViewController alloc] init];
upvc.cancelButton.hidden = true;
[self presentModalViewController:upvc animated:FALSE];
}
}
But for some reason it doesn't work. The debugger steps through the code without error, never the less, the second modal view controller isn't displayed.
First, I would suggest checking that your appDelegate.pin is blank and not nil. If it is nil, the if statement would not be satisfied and your second ModalView would not be presented.
You may also want to try the previous suggestion, calling presentModalViewController from viewDidAppear, or setting a delay if leaving it in viewDidLoad. It is possible that the CredentialsViewController is trying to present the second view when it has not yet presented itself.
The if statement is being hit and the second PresentModalViewController is executing without error, but it just wasn't displaying. I did try putting the code in ViewDidAppear and a load of other places as well, such as applicationWillBecomeActive etc. Although not actually crashing the code, still none of these approaches would show the view controller. In the end I have opted for this:
start with pin of #""
on applicationDidEnterBackground check if pin has been set
if yes
PresentModalViewController: PinViewController
if no
do nothing
Bit of a hack but it will do for now. I suppose I should put some sort of notification in somewhere warning that the pin hasn't been set. The suggestion about the delay may possibly work I suppose. I might give it a go in the future. Thanks guys....points up!

iPhone App - dismissing modal view controller doesn't dealloc it

I have a UIViewController (call it NumberTwo) which I presented as a modal view controller from another UIViewController (call it NumberOne). NumberTwo contains a touchesBegan method which listens for touches, and it also has an accelerometer method which listens for device orientation changes in the x, y, or z direction. NumberTwo has a button called "Done" which, when tapped, dismisses itself as a modal view controller:
[self dismissModalViewControllerAnimated:NO];
But it seems as though it's still listening for touches, and it's still listening for accelerations. How can I completely free up NumberTwo when I dismiss it? I tried adding a release call as follows:
[self dismissModalViewControllerAnimated:NO];
[self release];
but that caused a EXEC_BAD_ACCESS.
Did you release the controller after you presented it? E.g. in your method in NumberOneController that presents it, do you have something like:
NumberTwoController * controller = [NumberTwoController alloc] init];
// do stuff to config controller
[self presentModalViewController: controller];
[controller release];
Unless you want to hang on to NumberTwoController for re-use, this would be the usual pattern. The presentModalViewController method ensures that the controller is retained while it's in use. It should then get tidied up when, within NumberTwoController, you call [self dismissModalViewControllerAnimated: NO].
I had a very similar issue that plagued me for days. It turned out that my view controller class wasn't being deallocated when I dismissed it because that view controller had an active NSTimer that wasn't being invalidated (stopped). I was able to kill the timer in viewDidDisappear.
Make sure you are releasing everything you use when you finish with it; The dealloc method is only called when the UIViewController and all of its properties/objects are no longer in use. Never use [self release]; you need to release it from the view controller that created it after you are finished with it.

presentModalViewController calling any method in the target viewController?

When i call presentModalViewController
[self presentModalViewController:iPSPvc animated:NO];
is there a method i can implement in the target viewController (iPSPvc) that gets called every time this happens?
I need to make sure some updating of the view is done.
viewDidLoad gets called when i create an instance of iPSPvc so I need a method where I can do sometime similar.
Many Thanks
-Code
Try viewWillAppear method
-(void)viewWillAppear:(BOOL)animated
{
//your code goes here
}
what's with viewWillAppear and viewDidAppear?
- (void)viewWillAppear:(BOOL)animated
If I've understood your question aright, the above method (or one its close cousins) in your target viewController. This gets called every time the controller's view is about to appear, not just when the view is first loaded.

UINavigationController and viewWillDisappear

So I have a UINavController in my app and am trying to execute a method when the user presses the back button. I have searched everywhere and can only find bits and pieces that don't really make sense out of context.
Is there a way to implement some sort of check that catches when the user presses the back button to dismiss the current view? (the viewWillDisappear method for the view being popped never gets called for some reason. I did read that it doesn't unless you forward that call?) Does that sound right, and does anyone have any ideas or suggestions? Thanks in advance.
Take a look at the UINavigationControllerDelegate. There are the only two methods that get called when a UIViewController is pushed to the navigation controller stack. Similarly, if one is being pushed then something probably was just popped. This is what I did to call viewDidDisappear and viewWillDisappear.
# pragma mark - UINavigationControllerDelegate Methods
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
static UIViewController *vcPointer = nil;
// If the previous view controller is still around then let's send a viewWillDisappear message
if (vcPointer != nil) {
if ([vcPointer respondsToSelector:#selector(viewWillDisappear:)]) {
[vcPointer viewWillDisappear:animated];
}
}
// Keep track of a pointer to the current viewController
vcPointer = viewController;
[viewController viewWillAppear:animated];
}
This code keeps a pointer reference to the last view controller that was pushed so that once we push another one we can pop the last one (if it still exists).
AFAIK, if you add a UINavigationController to a UIView via code, it won't send those messages to it's subviews by default. It will only do this if the UINavigationController received these calls itself. Maybe this is your problem (I don't know your view setup).
So, when adding the view of the UINavigationController, be sure to manually send it these messages.
UINavigationController *navigationController = [UINavigationController alloc] initWithRootViewController:rootViewController];
[navigationController viewWillAppear:NO];
[aView addSubview:navigationController.view];
[navigationController viewDidAppear:NO];
At least, this is what I found during development. Been searching for this for a long time and I still don't understand the rationale behind it.
You can always hide the default back navigation button and create your own with its own method to be called when pressed.
Execute whatever code you want there then pop the view.
I used this solution:
Add a custom button on the left side in the navigation bar
Let that button activate a custom method.
Disadvantage of this workaround: you will lose that nice arrow shaped "back" button. That can be solved as well with a custom image.
So here is my code.
Put this in your viewDidLoad:
// LeftButton in Navigation Bar
UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonPushed:)];
self.navigationItem.leftBarButtonItem = leftBarButton;
[leftBarButton release];
Then add this method in the same .m file:
- (void) backButtonPushed: (id)sender {
// do what you want to do
}
dont forget in the .h file
- (void) backButtonPushed: (id)sender;
The viewWillDisappear & viewDidDisappear is called when a controller is popped or dismissed. The function is called on the fore-front view controller not on the UINavigationController itself. Did you possibly subclass and forget to call the super on something?

remove ViewController from memory

I hope to load an ViewController and do something then unload (viewDidUnload) it from memory.
if (self.vViewController5.view.superview==nil)
{
ViewController5 *blueController =
[[ViewController5 alloc] initWithNibName:#"View5" bundle:nil];
self.vViewController5 = blueController;
[self.vViewController5 setDelegate:self];
[blueController release];
}
[self presentModalViewController:vViewController5 animated:YES];
later, call
[self dismissModalViewControllerAnimated:YES];
but I found that dismissModalViewControllerAnimated does not trigger the event viewDidUnload of Viewcontroller5.
I try function release but it caused program collapse.
I also try removeFromSuperView but it does not trigger the event ViewDidUnload neither.
Welcome any comment
Thanks
interdev
viewDidUnload is only called when your application receives a memory warning, and the view is not active. It's generally used for releasing retained views (including IBOutlets). You can use viewWillDisappear or viewDidDisappear to respond to a dismissal (dealloc will also be called eventually, but not necessarily exactly when the view is dismissed).
A dismissed UIViewController will not trigger the viewDidUnload, as you have discovered. However it will trigger viewWillDisappear method, if that suit your needs.