I have a uibutton inside a uiScrollview inside a uiviewcontroller. When I click the button I want to be able to call a method in the uiviewcontroller.
I have the following action on my button that calls a method within my uiscrollview:
[categoryButton addTarget:self action:#selector(categoryButtonWasClicked:) forControlEvents:UIControlEventTouchUpInside];
But this just calls a method within my uiscrollview (which I will still keep). How do I then call a method in the viewcontroller??
Thank you for any help you can provide.
enter code hereTry doing something like this
#import <UIKit/UIKit.h>
#protocol myUIScrollViewProtocol <NSObject>
-(void)buttonWasPressInScrollView:(id)sender;
#end
#interface MyUIScrollView : UIScrollView
#property (weak, nonatomic)id myDelegate;
#end
Create a subclass of UIScrollView and add a delegate then assign your UIViewController as the delegate and implement the "buttonWasPress.." method in it.
Then from the categroryButtonWasClicked method in your uiScrollView:
-(void)categoryButtonWasClicked{
if ([self.myDelegate respondsToSelector:#selector(buttonWasPressInScrollView:)]){
[self.myDelegate buttonWasPressInScrollView:self];
}
...
}
in your viewController's .h add the following
#interface MyViewController : UIViewController <myUIScrollViewProtocol>
Related
I have a problem with IBAction delegate. I create button in xib file by Interface Builder and want to use it in another controller.
Button is clickable and I don't see any error but it don't show Alert or NSLog. If I try to do NSLog in LetterView.m, It's work perfectly fine but not in ViewController. What should i do?
Thanks for help.
What I am doing currently is:
LetterView.h
#import <UIKit/UIKit.h>
#class LettersView;
#protocol ButtonHint <NSObject>
-(void)hintButtonView:(LettersView*)letterView;
#end
#interface LettersView : UIView #property (strong, nonatomic) IBOutlet UIView *lettersView;
- (IBAction)hintButton:(id)sender;
- (IBAction)removeButton:(id)sender;
#property (nonatomic, assign) id <ButtonHint> hintDelegate;
#end
LetterView.m
-(IBAction)hintButton:(id)sender {
[self.hintDelegate hintButtonView:self];
}
ViewController.h
#interface GameViewController : UIViewController <ButtonDisplayChar, ButtonHint>
ViewController.m
-(void)hintButtonView:(LettersView *)letterView {
NSLog(#"DSfdfsadasda");
[self addAlert:#"HINT" andMessage:helpstr andButton:#"Thanks"];
}
You can do in other View controller by adding target of that Button
example : in your xib have button.
Use that button as target in other view controller.
example :
first in view controller
var letterVw : LetterView?
letterVw.myFirstButton.addTarget(self, action: #selector(myClass.pressed(_:)), forControlEvents: .TouchUpInside)
than
func pressed(sender: UIButton!) {
}
EDIT:
In my ViewController i am adding multiple buttons to its view.
ViewController1.h
#import <UIKit/UIKit.h>
#interface ViewController1 : UIViewController
-(void)buttonTapped:(id)sender;
#end
ViewController1.m
#import "MyViewCreatorClass.h"
#interface ViewController1 ()
#end
#implementation ViewController1
- (void)viewDidLoad {
[self.view addSubView:[MyViewCreatorClass createButtonWithParentView:self]];
}
-(void)buttonTapped:(id)sender{
NSLog(#"tapped");
}
The implementation for creating the button is inside the class 'MyViewCreatorClass'
MyViewCreatorClass.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "MainViewController.h"
#interface MyViewCreatorClass : NSObject
+ (UIButton*)createButtonWithParentView:(ViewController1*)parentView;
#end
MyViewCreatorClass.m
#import "MyViewCreatorClass.h"
#implementation MyViewCreatorClass
+ (UIButton*)createButtonWithParentView:(ViewController1*)parentView {
UIButton *button = [[UIButton alloc] initWithFrame:....];
//some other implementation (title, color etc.)
[button addTarget:parentView action:(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
return button;
}
#end
At first i had this implementation inside ViewController1 and it worked fine, but now
the warning "undeclared selector 'buttonTapped:'" shows up (this was solved by declaring the method buttonTapped: in ViewController1.h)
the method won't get called as i moved this method into MyViewCreatorClass.
I know that parentView needs to be an instantiated object, and it is. In another method of MyViewCreatorClass i'm also setting some views delegate to parentView and it works.
I even tried to use this method as an instance method not a class method but it did not work either.
What could it be that prevents the method from being called?
Additional question:
One could also use protocols to achieve this (comments). I know how to use protocols, but sadly i don't know how to implement this so a button calls a method on touchUpInside.
Any ideas?
I added a custom UIView to a UIViewController and after some code in the view, I want to remove this view from the UIViewController, but I am not sure how to notify the UIViewController of the UIView's removal.
I am using this method to exit from within the UIView
-(void)exit{
[self removeFromSuperview];
}
Do I need to set a listener? Any help is appreciated
I posted a detailed solution. Thanks Rage, Bill L, and FreeNickname
Since it is not convenient to write a code as a comment, I'll write it as an answer. This answer illustrates what #Rage suggested in his answer.
First, you create a #protocol for your CustomView and add a delegate for it. You declare that the delegate should conform to this protocol. Then in your ViewController you implement your protocol and set ViewController as a delegate of your CustomView.
Like so:
CustomView.h:
#protocol CustomViewDelegate<NSObject>
//You can also declare it as #optional. In this case your delegate can
//ignore this method. And when you call it, you have to check, whether
//your delegate implements it or not.
-(void)viewWasRemoved:(UIView *)view
#end
#interface CustomView: UIView
#property (nonatomic, weak) id<CustomViewDelegate> delegate;
#end
CustomView.m:
#implementation CustomView
-(void)exit {
[self removeFromSuperview];
//if your method is NOT #optional:
[self.delegate viewWasRemoved:self];
//if it IS #optional:
if ([self.delegate respondsToSelector:#selector(viewWasRemoved:)]) {
[self.delegate viewWasRemoved:self];
}
}
#end
ViewController.m:
#import "CustomView.h"
#interface ViewController()<CustomViewDelegate>
#end
#implementation ViewController
-(void)someMethod {
self.customView.delegate = self;
}
-(void)viewWasRemoved:(UIView *)view {
//Whatever
}
#end
Use delegation. Add a protocol to your custom View which implements a method to notify the removal of the subview.
Make the View controller the delegate while adding the custom view. In your custom class call the delegate method right before [self removeFromSuperview];
Set up a delegate for it, with a method called viewWasRemoved: or something similar. Set your view's delegate to be the ViewController you want to notify, and then in your exit method, call [self.delegate viewWasRemoved:self];, which will then kick off the viewWasRemoved: method in your ViewController, where you can do any relevant work you need to do once the view is removed.
I'll post a detailed solution in case it helps anyone out, or if anyone can offer any pointers. Thanks Rage, Bill L, and FreeNickname:
The answer is to use delegation
First I imported the superview to the .h of my subview:
#import "ViewController.h"
Then I add a delegate id to the same file:
#property (weak) id delegate;
Then when initializing the custom UIView in the superview, I set the delegate:
CustomView *view = [[CustomView alloc]initWithFrame:frame];
view.delegate = self;
I add this method in the superview for a callback:
- (void) viewWasRemoved: (UIView *) view{
NSLog(#"removed");
}
Then finally call the method in my subView:
-(void)exit{
[self.delegate viewWasRemoved:self];
[self removeFromSuperview];
}
I'm creating a custom UIView subclass (shareView) from a Nib.
I created a custom protocol for shareView like this:
#protocol sharePopupDelegate
#required
-(void)userPublishedContent;
-(void)userAbortedPublish;
#end
#interface shareView : UIView
{
id<sharePopupDelegate> delegate;
}
In my main.storyboard I created a custom UIViewController myViewController with a shareView view instance called "popup" inside.
So now I got
#property (weak, nonatomic) IBOutlet shareView *popup;
I would like now to delegate myViewController from shareView methods i declared, so I did
self.popup.delegate = self;
inside myViewController but the protocols' methods are not being called inside myViewController.
So i correctly see the shareView instance but cannot interface to its delegate.
Can you help me please?
Thanks in advance
Make sure that you have the protocol declared in myViewController.
For example
#interface MyViewController : UIViewCOntroller <sharePopupDelegate>
In this section of the code:
#interface shareView : UIView
{
id<sharePopupDelegate> delegate;
}
You are creating a strong reference to the delegate, which is not what you want most of the time. Change it to this:
#interface shareView : UIView
#property(weak, nonatomic) id<sharePopupDelegate> delegate;
The shareView class itself must have some way to know when a user publishes content. Maybe you have an action linked up to the shareView which calls a method in the shareView class. For examaple:
- (void)publishButtonTapped {
// some code
}
What you want to do is let the delegate know in that method, something like this:
- (void)publishButtonTapped {
// some code
[self.delegate userPublishedContent];
}
Then whatever action the user takes to cancel:
- (void)cancelButtonTapped {
// some code
[self.delegate userAbortedPublish];
}
Hope this helps.
I have a UIViewController which contains a UIView Subclass, from the subclass I want to call a method defined in the UIViewController which contains it. I do not want to instantiate a new instance of the view controller, because it contains information that I need within the method I am attempting to call. Here is a diagram trying to further clarify:
(UIViewController) MainView --> has method updateView
(UIView) SubView ---> Has Button that plays animation and has completion block
I want to call UpdateView in the completion block
I think you can set up a protocol in your Subview, which can be implemented by your ViewController
Your SubView.h
#class SubView;
#protocol SubViewDelegate <NSObject>
- (void)actionToPromoteToViewController: (NSString *)exampleString isSelected:(BOOL)exampleBool;
#end
Then, in your ViewController.h:
#interface MainViewController : UIViewController <SubViewDelegate>
and your ViewController.m, implement the method.
- (void)actionToPromoteToViewController: (NSString *)exampleString isSelected:(BOOL)exampleBool{
// Method Implementation
}
For 'correct' implementation you need a reference to view controller in your UIView Subclass:
#interface UIViewSubclass : UIView
...
#property UIViewControllerSubclass *viewController;
#end
Then set this viewController reference to your view controller and use it in completion block.
If you want a local solution (and not to extend UIViewSubclass with property) take a look at this answer: https://stackoverflow.com/a/3732812/326017