calling an method in a view controller from a child view - objective-c

In my ViewController I have created a view which contains a button and a bunch of other elements. When the button is pressed I want to call a method from the parent ViewController. I tried:
[self.superview buttonPressedMethod];
But the superview is no the ViewController but UIView. Is there anyway to do this?

This is exactly what the target/action mechanism is for. Make the method in the view controller an IBAction. Set the view controller as the button's target, and set the method as its action. That should be all you need to do.

At ParentViewController.h
-(void)ParentMethod;
At ParentViewController.m
-(IBAction)button:(id)sender {
[self ParentMethod];
}
At IBAction of Play Button on child view controller do this:
-(IBAction)ChildMethod:(id)sender {
ParentViewController *parent=self.parentViewController;
[parent ParentMethod];
}

Better create delegate in view controller and set delegate in child view, so when something occur call delegate method according to it.

Related

How to override the UIBarButtonItem triggered segue defined in a storyboard

I have a UIViewController in a storyboard iPhone app that I need to reuse in several places. In the storyboard, there is a UIBarButtonItem that has a triggered segue to another controller. In some cases, however, I would like to override the behavior of the button to segue to a different view controller. I'm thinking that there must be a way to either initialize the view controller with a message that specifies the target view controller, or to set some property after the controller is initialized but before it's pushed?
One challenge seems to be that segues can't be defined programmatically (based on what I've read so far), and I don't think I can have multiple segues on the same view controller in storyboard. So I may need to do something like this:
[self presentModalViewController:myNewVC animated:YES];
... rather than use a segue, but I'm not sure how to override the behavior of the button defined in storyboard to do it that way.
Any help is appreciated.
Just create an IBAction and a BOOL for some condition to pick which view controller should be instantiated.
UIViewController *viewController;
if (someCondition) {
viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"someViewID"];
}else{
viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"someOtherID"];
}
[self presentViewController:viewController animated:YES completion:nil];

Reference the main view controller... need the code

I have a view based app (not navigation or tab based...)
My main view controller is called from the app delegate and initiated from a xib.
Then I use presentModalViewController to bring another view on the screen with it's own xib and view controller.
I have no problems passing data to that view controller.
However, when I dismiss the second view controller, I want to send data back to the main view controller for my app, but I just can't figure out how to reference it. Actually, I'd like to call a method in the main view controller if possible.
I've been struggling with this a bit and have found suggestions online but I just can't seem to get it to work. I'm hoping someone can provide the sample code to do this.
P.s. is this "main view controller" still referred to as a "root view controller" or is that term only used when dealing with a view controller stack (i.e. navigation or tab view controller)
EDIT:
I'm sure Bryan's solution would work so I have accepted as answer. However I ended up using NSNotificationCenter to get this to work and I find it a bit simpler to understand as a beginner
You can use the delegation pattern. In your modal view controller's header file, create an interface for a new delegate protocol...
#protocol ModalViewControllerDelegate <NSObject>
- (void)sendData:(Data *)someData;
#end
...and give your ModalViewController a new instance variable that implements this protocol:
#property (nonatomic, assign) id<ModalViewControllerDelegate> delegate;
Your main view controller should implement this protocol...
#interface MainViewController : UIViewController <ModalViewControllerDelegate> {
...and set itself as the delegate before it presents the modal view controller:
ModalViewController *modalViewController = [[[ModalViewController alloc] init] autorelease];
[modalViewController setDelegate:self];
// Present modal view controller
The main view controller should implement the delegate protocol's method:
- (void)sendData:(Data *)someData {
NSLog("I have just received some data: %#", someData);
}
Then inside your modal view controller, you can simply call the following method whenever you want to send data back to the main view controller:
[delegate sendData:someData];

Check if View has been Removed or Not?

I have a UIView class which I am currently removing from my view by using from inside the class [self removeFromSuperview]. Hopefully that's the correct thing to do.
However, now from my view controller (of which I add this view to) I need to know when it has removed itself so that I can call a method when this happens.
Generally speaking, the view shouldn't be doing things like removing itself. That's the job of the view controller.
If a UIView subclass can produce events that require the view hierarchy to be changed, I would define a delegate property for that view, and when an event occurs, call a method on that delegate. Then, when your view controller adds the view, it would set itself as the delegate and define the relevant method to handle the event.
If you have removed the UIView
view.removeFromSuperview()
you can check if it exists with the following code:
if !(view.superview != nil) {
//no superview means not in the view hierarchy
}
You could have a delegate callback setting the controller as the view's delegate. When you're about to remove the view, make the delegate callback and implement the callback method in your controller.
The 'removeFromSuperview' has always seemed backwards to me… :(
I'm assuming you are making the remove call after some sort of action, like a button press or something. if that is the case, set the buttons delegate to be the view controller, not the view class, and inside the action method in the view controller, call
[yourCustomView removeFromSuperview];
The best choice would be to let the controller remove the view
[self.view removeFromSuperview];
and to know if the view was removed (or never added) you can ask
if(![self.view superview]) {
//no superview means not in the view hierarchy
}
Not sure what sdk you are using - but I am using iOS 5 and I just use the following method in the superview:
-(void)willRemoveSubview:(UIView *)subview{
if([subview isEqual:someView]){
//do stuff
}
//you could do some stuff here too
}

disable dismissal of uipopoverview controller

UIPopoverController automatically dismisses when we tap or touch outside the popoverview.
I want to restrict this automatic popover dismissal.
self.myPopovercontroller.passthroughViews=[NSArray arrayWithObject:self.view];
Duplicate of "is there a way NOT to have the popover dismissed when pressing outside it?"
There is a very simple and legit solution. In the view controller that presents your UIPopoverController, conform to the UIPopoverControllerDelegate protocol and implement the following delegate method. I just tested this and it does prevent popover to dismiss.
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return NO;
}
Just make sure that you have set the delegate of your popover controller to the view controller that implements this.
You can dismiss the popover by using [popoverController dismissPopoverAnimated:NO]; method.
Have a read of the UIPopoverController documentation. Specifically...
When displayed, taps outside of the popover window cause the popover
to be dismissed automatically. To allow the user to interact with the
specified views and not dismiss the popover, you can assign one or
more views to the passthroughViews property. Taps inside the popover
window do not automatically cause the popover to be dismissed. Your
view and view controller code must handle actions and events inside
the popover explicitly and call the dismissPopoverAnimated: method as
needed.
Implement popoverControllerShouldDismissPopover: in the delegate, and you can stop it from disappearing unless you want it to.

iOS Dev, How can I call a method in the super class of my UIViewController?

i have two UIViewControllers for example A and B.
On A there is a button when pushed loads view B as a sub view. Using the standard initWithNibName. On B there is a button which dismisses View B and should call a method in view A (its Parent View). I thought it should be a simple [super methoddName:perimeter] but this doesn't work. after placing a NSLog printing out the name of the parentViewController it returned null which is odd as surly it should return View A as the Parent view.
any Ideas Cheers
super refers to your class's superclass, not its parent view controller.
A way to quickly do this is create a new init method that takes an instance of view controller A, use that to set the target of your button.
The best way is to define a new protocol on view controller B. Make view controller A conform to it. On init of B, pass in a refernce to A to use as your delegate. Then on the button push in B call the desired method on the delegate.
You might be better off by letting view controller A be a delegate on view controller B.
A can set the delegate property on B when after loading it but before pushing it into view, and when B needs to call the required method, it can just call it on the delegate object.
That makes the coupling between the controllers looser, and if you let the delegate conform to a protocol, you can keep B's knowledge of A to a minimum.
It's better design, if you ask me.
parentViewController won't work if you add view controller B's view as a subview. You will have to find the view controller A in a different way.
Say, if you had added B's view as a subview like this,
[A.view addSubview:B.view];
then you can call view controller A like this.
[[B.view.superview nextResponder] methoddName:perimeter];
If you have added B.view as a subview somewhere within the view hierarchy of A.view.
UIResponder * responder = B.view.superview;
do {
responder = [responder nextResponder];
} while ( ![responder isMemberOfClass:[A class]] );
// `responder` is referencing your view controller A. You will have to cast it.
Easiest way to do this especially if it is a static method:
ViewControllerB
#import "ViewControllerA.h"
- (void)dismissView{
//implementation to close the view
[ViewControllerA methodName:perimeter];
}
Good Luck!