Run a method in a UIViewController from its view

I have a UIViewController with its UIView that contains a UIButton . I want to call a method in a UIViewController on a button click event.
Saving a UIViewController link UIViewController not seem like a good idea, as shown in the following link: Get a UIViewController from a UIView?

So, I want to achieve this using a delegate. Any hint on how to achieve this?

+5
source share
7 answers

You can do something like this

CustomView.h

 #import <UIKit/UIKit.h> @protocol CustomViewDelegate <NSObject> -(void)didButtonPressed; @end @interface CustomView : UIView @property (assign) id<CustomViewDelegate> delegate; @end 

CustomView.m

 #import "CustomView.h" @implementation CustomView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.backgroundColor = [UIColor whiteColor]; //[self addSubview:titleLbl]; UIButton *button= [UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame = CGRectMake(100, 100, 100, 50); [button addTarget:self.delegate action:@selector(didButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [button setTitle:@"pressMe" forState:UIControlStateNormal]; [self addSubview:button]; } return self; } 

in ViewController.m

 -(void)loadView { [super loadView]; CustomView *view = [[CustomView alloc]initWithFrame:self.view.bounds]; view.delegate = self; [self.view addSubview:view]; } 
+9
source

For this, a chain of respondents was created. When you add a target to your button, just set nil for the target:

 [mySpecialButton addTarget:nil action:@selector(mySpecialButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 

The purpose of nil basically means "send mySpecialButtonTapped: to any object in the responder chain that can handle it."

Now you can handle this selector anywhere in the responder chain, which includes the button itself, its containing view, containing the view controller, UIApplication, and finally your AppDelegate. Just put this method in the object most suitable for your needs:

 - (void)mySpecialButtonTapped:(id)sender { NSLog("My special button was tapped!"); } 

You do not need delegates or callback blocks (as in the accepted answer) if you just want to release the message up.

+3
source

I assume that you expected something more fundamental, and then just passed the action of the button to the controller. I always follow the MVC pattern when the model / view / controller works together. It solves your problem and many others. And I want to share my experience.

  • A separate controller from the view and model: do not put all the "business logic" in the classes associated with the view; this makes the code very unusable. Create controller classes to host this code, but make sure the controller classes do not make too many assumptions about the presentation.
  • Define a callback API using @protocol using @optional , if not all methods are necessary.
  • For a view, define a protocol, for example, <view class name>Protocol (NewsViewProtocol example). For the controller, define the delegate as <view class name>Delegate (example NewsViewDelegate) and dataSource, for example <view class name>DataSource (example NewsViewDataSource). Store all these @protocols in a single file named <view class name>Protocol.h (NewsViewProtocol.h example)

A brief example:

NewsView.h Content

 // // NewsView.h @interface NewsView : UIView <NewsViewProtocol> { @protected NSObject* delegate_; NSObject* dataSource_; } @end 

Content of NewsController.h and .m

 // // NewsController.h @interface NewsController : UIViewController <NewsViewDataSource, NewsViewDelegate> { } @property (nonatomic, weak) UIView<NewsViewProtocol>* customView; @end @implementation NewsController - (void)viewDidLoad { [super viewDidLoad]; self.customView = (UIView<NewsViewProtocol>*)self.view; [self.customView setDelegate:self]; [self.customView setDataSource:self]; } @end 

Content NewsViewProtocol.h

 // // NewsViewProtocol.h @protocol NewsViewProtocol; @protocol NewsViewDelegate<NSObject> @optional - (void)someAction; - (void)newsView:(UIView<NewsViewProtocol>*)newsView didSelectItemAtIndexPath:(NSIndexPath *)indexPath; @end @protocol NewsViewDataSource<NSObject> @required - (id)newsView:(UIView<NewsViewProtocol>*)newsView itemAtIndexPath:(NSIndexPath *)indexPath; - (NSInteger)numberOfItemsInNewsView:(UIView<NewsViewProtocol>*)newsView section:(NSInteger)section; - (BOOL)newsView:(UIView<NewsViewProtocol>*)newsView shouldDisplaySection:(NSInteger)section; @end @protocol NewsViewProtocol<NSObject> @required //Never retain delegate instance into implementation of this method - (void)setDelegate:(NSObject<NewsViewDelegate>*)delegate; //Never retain delegate instance into implementation of this method - (void)setDataSource:(NSObject<NewsViewDataSource>*)dataSource; - (void)reload; @end 

You can assume that it is redundant. In a simple view controller, YES. But if you are developing a very complex screen with a huge amount of data, then it gives you some advantages:

  • Helps you share responsibility between a view and a controller.
  • Saves your code.
  • Makes the code more reusable.
+1
source

Life is easy in xcode.

At the very beginning, make sure your xib View (the one that has the button inside it) is associated with the correct ViewController class. What could be the default ViewController class that comes with the new project or your custom one.

After that, a magic trick comes here! Separate your view into 2 panels. The goal is to see your xib and your viewController code (.m file). Now press the control key on your keyboard and drag your UIButton into the code. Choose IBAction. It will generate what you can call a “listener” in another language. Go to the main code of your view controller and fill out this method!

Just! Good luck :)

0
source

You really don't need delegates for this, since UIButtons are for use. Just click “Control” and drag it using the .m file button for your UIViewController. This will create a new method. From there, you can make a call to the method that you wrote, or simply copy-paste what you have into a new method.

-1
source

To add a button programmatically, in myViewController.m

 UIView *yourView = [[UIView alloc] init]; UIButton *yourButton = [[UIButton alloc] initWithFrame:CGRectMake(0,0,100,21)]; [yourButton addTarget:self action:@selector(yourMethod) forControlEvents:UIControlEventTouchDown]; [yourView addSubview:yourButton]; 

More details here .

-1
source

You can try the following:

 [yourButton addTarget:self action:@selector(yourButtonAction:) forControlEvents:UIControlEventTouchUpInside]; 

And in your selector specify the action

 - (IBAction)yourButtonAction:(id)sender { //Action to perform } 
-1
source

All Articles