iOS Delegate Does Not Push or Present a View - ios

I have a HomeView and a HomeDropDownView.
HomeDropDownView is shown as a drop-down view over the HomeView.
HomeView is a delegate of HomeDropDownView.
When I do an action in HomeDropDownView I want to call a delegate method in HomeView and have that delegate method present a third view controller, TestViewController from it's navigation controller.
If I try to launch TestViewController from anywhere in the class it works fine - except from the delegate method.
There are animations in HomeDropDownView but putting the call to the delegate method in the complition does not make the view controller appear. And in the case that I'm using this the animation's don't fire anyway; there's only a resizing without animation.
TestViewController's init does get called as well as the viewDidLoad but not the viewWillAppear and the view dose not appear.
Code:
HomeDropDownView
- (void)finalAction {
...
[self callDelegateAction];
...
- (void)calldelegateAction {
if ([self.delegate respondsToSelector:#selector(launchTestView)] ) {
[self.delegate launchTestView];
} else {
DLog(#"Error out to the user.");
}
}
HomeView
- (void)launchTestView {
//[self listSubviewsOfView:self.parentViewController.view];
NSLog(#"delegate method | self: %#", self);
TestViewController *tvc = [[TestViewController alloc] initWithNibName:#"TestViewController" bundle:nil];
//[self.navigationController presentViewController:tvc animated:YES completion:nil];
//[self.view.window.rootViewController presentViewController:tvc animated:YES completion:nil];
//[self.navigationController pushViewController:tvc animated:YES];
AppDelegate *appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appdelegate.tabBarController.navigationController presentViewController:tvc animated:YES completion:^() {
NSLog(#"Done!");
}];
}
None of the above approaches work. But if I put the exact same code into the viewDidAppear or put it in a button action method, it will work fine. At the time of calling the delegate method's self is HomeView and all the subviews, including the nav controller do seem to be there. This is in a tabcontroller-based project but I think that any of the above are acceptable ways to call the nav controller still.
What am I missing? Why does my delegate method not want to push/present a viewcontroller on HomeView's Nav controller? It's probably something I'm missing but I can't find a reason in the Apple Docs or any other thread.
Thanks for the help!

Sadly this turned out to be that HomeView was being changed underneath the execution of the message. So by the time the HomeView got the message call it was no longer the same HomeView object that had requested action in the first place. So it was not the same delegate.
This was done so that it would appear to the user that the same view was being used for different things.
But this is a good example of why you should not destroy and re-create critical views. We should have been using the same view and reloading the objects instead if we knew that we would be sending messages. Or had some notion of a control structure.

Related

Calling method from self.parentViewController does nothing

After dismissing my second view controller, I would like to call a function in my first view controller.
The code I am using now is this
firstViewController *fvc = (firstViewController *)self.parentViewController;
[self dismissViewControllerAnimated:YES completion:^ {
[fvc someMethod];
}];
But it seems that the method is never called, I added a UIAlertView to the method so it would be called the moment the method is called too.
firstViewController *fvc = (firstViewController *)self.parentViewController;
[fvc someMethod];
[self dismissViewControllerAnimated:YES completion:nil];
This totally fails too, I don't get any error from both ways.
firstViewController *fvc = (firstViewController *)self.parentViewController;
[self dismissViewControllerAnimated:YES completion:^ {
[fvc someMethod];
}];
You should use presentingViewController insteadof parentViewController when self is being presented
like
firstViewController *fvc = (firstViewController *)self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^ {
[fvc someMethod];
}];
As rdurand said, try presentingViewController instead. Also, would be very helpful if you could put in a NSLog() in your code to show you what's in fvc at the point of method invocation. rdurand is probably right that your fvc pointer is nil, so you're invoking the method on nothing. If the method isn't activating, then there are really only a few possibilities:
Your line of code is not executing
It's executing, but you're invoking the method on a nil object
The method is executing, but on a different object than you're expecting
Set a breakpoint, look at your VC pointer, make sure the code is following the path you think it is. Pretty standard debugging task, unless I'm missing something...
As I commented, the UIViewController documentation states :
parentViewController
The parent view controller of the recipient.
(read-only)
#property(nonatomic, readonly) UIViewController *parentViewController
Discussion
If the recipient is a child of a container view controller,
this property holds the view controller it is contained in. If the
recipient has no parent, the value in this property is nil.
Prior to iOS 5.0, if a view did not have a parent view controller and
was being presented, the presenting view controller would be returned.
On iOS 5, this behavior no longer occurs. Instead, use the
presentingViewController property to access the presenting view
controller.
So basically, they did not really remove parentViewController, but the behavior you could expect before iOS 5 when your view controller doesn't have a parent view controller has changed.

Presenting two UIViewControllers, one after another

I am new to iOS development and I am doing little project as a research.
I have an app where after I start it I am showing MainViewController, but if this is the first launch of this app I want to show Sub1ViewController (names are made up) using presentViewController method called in MainViewController.
After user puts in some data on Sub1ViewController I invoke dismissViewController method to hide it.
The hard part starts here - I have no idea how to capture the event when Sub1ViewController is dismissed and I can present Sub2ViewController also using presentViewController invoked from MainViewController. All the time I am getting messages that I am trying to present view when another present or dismiss is in progress.
PS: I am using Xamarin, but I also understand objective-c.
hi you can try out this
[self dismissViewControllerAnimated:YES completion:^{
//code to be executed with the dismissal is completed
// for example, presenting a vc or performing a segue
}];
you can write code after completion of dismiss one view controller
or
You can achieve this by present view after some delay in dismiss method
-(void)onDismisViewController{
[self performSelector:#selector(presentSecoundViecontoller) withObject:self afterDelay:1];
}
-(void)presentSecoundViecontoller
{
SecoundViewController *secoundVC = [[SecoundViewController alloc] initWithNibName:#"secoundVC" bundle:nil];
[self.navigationController presentViewController:secoundVC animated:YES completion:NULL];
}
EDIT
Try this i Try and it work
crate one delegate Method in subviewcontroller1 and set delegate in mainviewcontroller and implement method in mainvie and present subviewcontroller2 in this delegate method its work
try this if not let me know will post code.
Delegate Creation on subviewcontroller1.h file
#protocol st1Protocol <NSObject>
- (void)presentViewController;
#end
#interface SubViewController1 : UIViewController
#property (nonatomic,assign) id <st1Protocol> delegate;
- (IBAction)dissmiss:(id)sender;
SubViewcontroller1.m file
i put dismiss view on button click of subviewcontroller1 you do this in you dismiss method
- (IBAction)dissmiss:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
//code to be executed with the dismissal is completed
// for example, presenting a vc or performing a segue
[self.delegate presentViewController];
}];
}
now implementation of this delegate method in main view controller.
implement delegate method in .h file
#interface StViewController : UIViewController<st1Protocol>
set delegate in mainviewcontroller.m file view didload
- (void)viewDidLoad
{
[super viewDidLoad];
subViewcontroller1 *st1=[[subViewcontroller1 alloc]initWithNibName:#"subViewcontroller1" bundle:nil];
st1.delegate=self;
[self presentViewController:st1 animated:YES completion:nil];
// Do any additional setup after loading the view from its nib.
}
delegate method implementation in main view controller
-(void)presentViewController{
SubmViewcontroller2 *st2=[[SubmViewcontroller2 alloc]initWithNibName:#"St2ViewController" bundle:nil];
[self presentViewController:st2 animated:YES completion:nil];
}
hope this may help you happy coding.

viewWillDisappear not called when calling popToRootViewControllerAnimated

I work on a legacy application, and have found out, that my view[Will/Did]Disappear methods are not always fired properly.
The case is, I have a (custom) UIViewController set as rootViewController in AppDelegate. This rootViewController has a UINavigationController, which has two view controllers pushed on it. When the user presses the home button, the user is logged out. When he later returns to the app, the application calls [UINavigationController popToRootViewControllerAnimated:YES] and then displays a modal UIViewController for logging in.
The problem is: When I push/pop on the UINavigationController normally, my viewWillDisappear method is called properly. But when I use the popToRootViewControllerAnimated: method, viewWillDisappear is not called on any of the viewControllers that are popped off.
Searching on the internet has only given two possible reasons:
If using a UINavigationController as a subview, you must call view[Will/Did]Disappear yourself
Not calling the proper super methods
None of these suggestions are the case in my app. And I have no idea where to look. Anybody has a suggestion to what has been done wrong in the app?
The view probably wasn't onscreen. It has to be onscreen (visible) for the viewWillDisappear: method to be called. If it's coming back from the background, it wasn't visible.
You could try using willMoveToParentViewController: which is called when the view controller is removed from its parent.
such useful to me
[nav performSelector:#selector(popToRootViewControllerAnimated:) withObject:nil afterDelay:0.0];
I rewrote UITabBarController
- (void)setSelectedIndex:(NSUInteger)selectedIndex {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UINavigationController *navigationController = [originalViewController as:[UINavigationController class]];
if (navigationController.presentedViewController) {
[navigationController dismissViewControllerAnimated:NO completion:^{
[navigationController popToRootViewControllerAnimated:NO];
}];
}else if (navigationController.topViewController){
[navigationController popToRootViewControllerAnimated:NO];
}
});
}

A method that dismisses a `modalViewController` and presents another

The thing is: I have a modalViewController presented with a button that triggers an IBAction like this:
-(IBAction)myMethod
{
[self dismissModalViewControllerAnimated:YES];
if([delegate respondsToSelector:#selector(presentOtherModalView)])
{
[delegate presentOtherModalView];
}
}
in the root view that is the delegate for that modalViewControllerI've implemented the presentOtherModalView delegate method and it looks like this:
-(void)presentOtherModalView
{
AnotherViewController *viewInstance = [[AnotherViewController alloc]initWithNibName:#"AnotherViewController" bundle:nil];
viewInstance.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:viewInstance animated:YES];
[viewInstance release];
}
The problem is this second modalViewController is not being presented. It gives me the message wait_fences: failed to receive reply: 10004003... How should this be done?
Because they are executed exactly after each other (they don't wait for the view to disappear/appear), it doesn't get executed. Because there can only be one ModalViewController on the screen at a time, you have to first wait for the other ModalViewController to disappear before the next one is put on screen.
You can do this creatively how you want, but the way I did it was something like:
[self dismissModalViewControllerAnimated:YES];
self.isModalViewControllerNeeded = YES;
And then in the underlying ViewController, in the viewDidAppear method, I do this:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.isModalViewControllerNeeded) {
[self presentModalViewController:viewInstance animated:YES];
self.isModalViewControllerNeeded = NO;
}
}
Hope it helps!
It is because the dismissModalViewControllerAnimated takes some time to dismiss with animation and you are calling another view to present as modal view before dismissing the 1st modal view so the presenting modal view call was rejected. You should not perform animations when you are not on the view after completely dismissing only you can call another view. To solve this problem call the present modal view after 2 or 3 seconds using time interval or use completion block for dismissModalViewControllerAnimated
You can achieve it by using this
[delegate performSelector:#selector(presentOtherModalView) withObject:nil afterDelay:3];

viewDidDisappear not called when use presentViewController

I have an UIViewController having this method:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(#"DISAPPEAR");
lastKnownOrientation = [self interfaceOrientation];
}
-(void)openSendVC{
SendMsgViewController *vc = [[SendMsgViewController alloc]initWithNibName:#"SendMsgViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:NO];
}
In the second view controller (SendMsgViewController) viewDidLoad I have the following:
[self presentViewController:picker animated:YES completion:NULL];
where picker is an UIImageViewPicker.
The problem is, when I call the method openSendVC a new controller is opened, but viewWillDisappear (of the first viewController) is not called.
That is the correct behavior. Here's an excerpt about viewWillDisappear: from the UIViewController API docs:
This method is called in response to a view being removed from a view hierarchy. This method is called before the view is actually removed and before any animations are configured.
Presenting a new view controller so that it hides the other view controller doesn't count as the view disappearing—only actually being removed from a view hierarchy does (e.g., with something like popViewControllerAnimated:).

Resources