0

I was trying to find a way to recognise a touch&hold on my buttons. I thought that to subclass my buttons was a good idea, but I'm now struggling with the whole idea of subclasses, parentsviews and the viewcontroller. So please forgive, I fear that this is a beginner's question:

How do I call a method (which I've defined in my ViewController) from a subclassed UIButton?

  • [self someMethod]; doesn't work - as UIButton is not a descendent of my ViewController.
  • [super someMethod]; doesn't work either - same problem I suppose
  • [self.superview someMethod]; ... again no luck
  • [MyViewController someMethod]; doesn't work either -- as it is 'undecleared' -- do I have to import my ViewController? Or do some kind of protocol/class call?

Any help would be very much appreciated.

Here is my subclass:

        //
    //  MoleButton.h
    //

    #import <Foundation/Foundation.h>


    @interface MoleButton : UIButton {
        int page;
        NSString *colour;

UIViewController *theViewController;

        NSTimer *holdTimer;

    }

    @property (nonatomic, assign) int page;
    @property (nonatomic, assign) NSString *colour;

    @end

    //
//  MoleButton.m

#import "MoleButton.h"


@implementation MoleButton

@synthesize page, colour;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    [self.superview touchesBegan:touches withEvent:event];

    [holdTimer invalidate];
    holdTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(touchWasHeld) userInfo:nil repeats:NO];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    [self.superview touchesMoved:touches withEvent:event];

    [holdTimer invalidate];
    holdTimer = nil;

}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    [self.superview touchesEnded:touches withEvent:event];
} 

- (void)touchWasHeld
{
    holdTimer = nil;
    // do your "held" behavior here

    NSLog(@"TOUCH WAS HELD!!!!");

    [self.theViewController doSomething];

}


@end
n.evermind
  • 11,944
  • 19
  • 78
  • 122

2 Answers2

2

You can simply add a property in the subclassed UIButton class, which holds the view controller. When initializing it, you need to add the controller, for sure.

cem
  • 3,311
  • 1
  • 18
  • 23
  • Thanks so much, but how exactly do I do that? @property (nonatomic, retain) ViewController MyViewController? Do I add the controller by #importing it? – n.evermind May 30 '11 at 12:30
  • 1
    You've already created properties in your subclassed UIButton. Add another (UIViewController *myViewController) the same way, after you initialized the Button, add the viewController with ([yourbutton setMyViewController:self]; and call it within your UIButton subclass with [self.myViewConroller yourMessage]; – cem May 30 '11 at 12:32
  • Thanks so much again, but I don't get this to work. I now get the error message 'Accessing unknown theViewController getter method when I call [self.theViewController doSomething]; – n.evermind May 30 '11 at 13:03
  • Also, I get the warning that the button (I initialised in the viewController) may not respond to setTheViewController... – n.evermind May 30 '11 at 13:04
  • How did you implement your property? – cem May 30 '11 at 13:09
  • UIViewController *theViewController; see the updated code above – n.evermind May 30 '11 at 13:22
  • Sorry, I just realised that I need to do @property and @synthesie commands as well. – n.evermind May 30 '11 at 13:25
  • The only remaining problem that I have is that I get the warning that self.theViewController may not respond to -doSomething... why is that? Thanks so much for your help. – n.evermind May 30 '11 at 13:43
  • 1
    Instead of UIViewController use the name of your controller class. Don't forget to import the header file. – cem May 30 '11 at 13:47
  • Hmm... if I do that, i.e. MyViewController *theViewController; (and do #import "MyViewController.h", I only get the error 'expected specifier-qualifier-list before 'MyViewController'... – n.evermind May 30 '11 at 15:41
2

Use the very simple delegate concept of Objective-C .

Check my answer in the below post for using delegate in Objective-C .

How do I set up a simple delegate to communicate between two view controllers?

Community
  • 1
  • 1
Jhaliya - Praveen Sharma
  • 31,697
  • 9
  • 72
  • 76
  • 1
    This is a cleaner approach. This doesn't tie your button to your view controller and gives you an opportunity to reuse it later. – Deepak Danduprolu May 30 '11 at 12:36
  • @Deepak: Thanks... but I got a headache trying to understand this... it's not really what I would define as simple. Perhaps I need more time to get my head around this. For the time being, I stick with unset's apparently 'uncleaner' approach. – n.evermind May 30 '11 at 13:27
  • 1
    @n.evermind : The delegate concept is something which is widely used in Objective-C programming, it would be better if you spend some time to understand it and will be helpful for you in many situations .. – Jhaliya - Praveen Sharma May 30 '11 at 13:46