if Delegate sends gesture messages do they conform to my customised Objective C protocol?
Asked Answered
R

0

3

I am trying to send gesture messages from several subclassed UIViews to common handlers in a UIViewController called TouchController. I am using a customised protocol to address a question arising from the answer to my previous SO post.

Messages are now sent from OneOfSeveralSubviews using a customised protocol called FirstGestureRecognizerDelegate but none of the handlers respond even though the code compiles with 0 warnings. I am confident the problem is not in TouchController for reasons stated previously. And after looking at more references (below) and checking out possible duplicates (below) I am now looking for answers to a new set of questions.


See Note (below) for my response to a possible duplicate question.


Here is my customised protocol

OneOfSeveralSubviews.h

#import <UIKit/UIKit.h>

@protocol FirstGestureRecognizerDelegate <NSObject>

- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer;
- (void)handleTapSelect:(UITapGestureRecognizer*)gestureRecognizer;
- (void)handlePan:(UIPanGestureRecognizer*)gestureRecognizer;

@end

@interface OneOfSeveralSubviews : UIView
{
    CGRect touchFrame;
}

- (id)initView:(CGRect)rect;

@property (nonatomic, weak) id<FirstGestureRecognizerDelegate> delegate;

@end

In the implementation of OneOfSeveralSubviews, gestures are defined by declaring instances of UILongPressGestureRecognizer, UITapGestureRecognizer and UIPanGestureRecognizer and setting their delegate properties

e.g.

UILongPressGestureRecognizer *longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:(id)self.delegate 
                                                                                          action:@selector(handleLongPress:)];
[longPressGR setDelegate:(id)self.delegate];

The program runs but is unresponsive. I’m not sure if this happens because it [a] sends messages that conform to a protocol the handlers ignore OR [b] can’t find a way to send messages that conform to a protocol the handlers recognise. References I’ve looked at give no clue whether it is [a] or [b]. Moreover this document uses the term subclassing to mean something different to subclassing in my situation and the illustrated code examples are in Swift rather than Objective C.

This leads me to ask:

  1. can UILongPressGestureRecognizer, UITapGestureRecognizer and UIPanGestureRecognizer actually be used with my customised protocol ?
  2. or does a customised protocol also require customised gesture recognition methods rather than standard methods (i.e. pre-fixed with UI) ?
  3. either way, are there simple code changes that would let the delegate send gesture messages that conform to the customised protocol ? or
  4. is it possible I’m trying to do something that is conceptually flawed ?

I’d welcome answers to these questions or a better question if there is one.

OneOfSeveralSubviews.m

#import "OneOfSeveralSubviews.h"

@implementation OneOfSeveralSubviews

- (id)initView:(CGRect)rect
{
    self = [super initWithFrame:rect];
    if (self)
    {
        // Set view size and color

        UILongPressGestureRecognizer *longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:(id)self.delegate action:@selector(handleLongPress:)];
        [longPressGR setDelegate:(id)self.delegate];
        [longPressGR setMinimumPressDuration:0.6f];
        [longPressGR setNumberOfTapsRequired:1];
        [longPressGR setNumberOfTouchesRequired:1];
        [hotspot addGestureRecognizer:longPressGR];

        // Create and configure two other gesture recognizers

        self.userInteractionEnabled = YES;
    }
    return self;
}

@end

TouchController.h

#import <UIKit/UIKit.h>
#import "OneOfSeveralSubviews.h"
#import "TwoOfSeveralSubviews.h"

// #import "ThreeOfSeveralSubviews.h"
// #import "FourOfSeveralSubviews.h"
//          etc.

@interface TouchController : UIViewController <FirstGestureRecognizerDelegate, SecondGestureRecognizerDelegate>
{
    CGRect touchFrame;
    CGRect screenFrame;
}

@property (strong, nonatomic) NSTimer *timer;

@end

TouchController.m

#import "TouchController.h"

@interface ViewController ()

@end

@implementation TouchController

- (void)viewDidLoad {
    [super viewDidLoad];

    OneOfSeveralSubviews *oneForAll=[[OneOfSeveralSubviews alloc] initView:[UIScreen mainScreen].bounds];
    [self.view addSubview:oneForAll];    
}

I've looked through these related posts:

NOTE

I checked Scott’s duplicate question and it is definitely asking a question similar to those being asked here. But in Scott’s example it also looks as if delegation that originates inside the ViewController is destined for a target outside the Viewcontroller (i.e. in MakePlantTVC). Whereas in my case, delegation that originates outside the ViewController is destined for a target inside the ViewController. For that reason I would never have picked Scott’s question as a duplicate even though to a more experienced person such a difference might seem insignificant.

These possible duplicates are very similar but don't solve my problem:

Rhizotomy answered 15/3, 2018 at 22:52 Comment(10)
You don't seem to ever create an object to act as the delegate.Octo
one quick point, have you considered moving to Swift? it is incredibly better (and easier as a bonus)Pvc
Other than that, what you're doing is totally fine. And good research!Octo
I don’t understand your comment but I suspect you could be saying what Paul was trying to tell me here - https://mcmap.net/q/357310/-if-duplicate-protocol-definition-of-39-uigesturerecognizerdelegate-39-is-ignored-how-can-i-define-targetsRhizotomy
I guess I needn’t worry about q.4. BTW, a neat edit! (I never know what to leave out). I missed this duplicate. I’m checking it out. Thanks on all counts.Rhizotomy
Fattie, I can't wait to move to Swift. I need to tie this up app that began with iOS4Rhizotomy
@JoshCaswell, I've worked out my response to the duplicate question. See my edit.Rhizotomy
You're missing the tree for the forest. This "inside"/"outside" distinction has no relevance. You haven't created a delegate. Nothing happens because nothing is there to make it happen. When you say initWithTarget:(id)self.delegate, self.delegate is nil.Octo
This shouldn't have been reopened. The answer at the dupe says this, very first thing: "Have you set the delegate? It might sound stupid but when a delegate doesn't work it's because I forget..."Octo
Let us continue this discussion in chat.Rhizotomy

© 2022 - 2024 — McMap. All rights reserved.