如果 'UIGestureRecognizerDelegate' 的重复协议定义被忽略,我该如何定义目标

if Duplicate protocol definition of 'UIGestureRecognizerDelegate' is ignored how can I define targets

更新 2

尽管问题仍然存在,但当前形式的问题已得到回答和接受。 代码现在编译时出现 0 个警告,但仍然对手势没有响应。一旦问题得到解决,代码将被更新,希望通过准备新问题的过程。已 post 编辑了一个新问题 here


据我所知,在我读过的任何 post 中从未有人问过或回答过这个问题(请参阅下面 可能的重复项)。

我正在尝试编写 Objective C 测试代码,以从 iPhone 屏幕上由矩形 UIView 定义的任何区域发送长按、点击或平移消息。到目前为止,如果 UIView 和处理程序方法都位于 UIViewController 中,我可以使用 UILongPressGesture, UITapGestureUIPanGesture 可靠地发送离散或连续消息。

最终我想从几个子类 UIViewsUIViewController 中的通用处理程序发送手势消息,但是当我尝试这样做时遇到了问题。在编写代码时,我研究了一份 Apple 文档,其中介绍了将委托用于 UIGestureRecognition 以及 Touches 中的 Objective C 方法( 请参阅下面的注释)和在 SO posts 中找到的示例(下面的链接)。

代码无法响应手势输入。最初它编译时有四个警告和两个问题:

  1. 重复协议

Duplicate protocol definition of 'UIGestureRecognizerDelegate' is ignored


更新 1

此问题现已解决。 澄清了一个我直到现在才明白的观点。作为回应,我更改了协议的名称,测试了代码并在 post 中更新了它。

OneOfSeveralSubviews.h 中,协议现在称为 FirstGestureRecognizerDelegate.ViewController 中进行了相关更改,例如

@interface ViewController : UIViewController <FirstSubviewGestureDelegate, SecondSubviewGestureDelegate>

  1. 未声明的选择器。

通过键入代表 属性 来消除三个警告 - 即插入 id 推荐 here) - 具有类似的更改对三个手势声明进行 - 即 initWithTarget:(id)self - 将委托 属性 添加到 self 的每个实例,以便将消息发送到预期目标 - 即 (id)self.delegate 而不是 (id)self

之前编译的代码有一个警告,但仍然对手势没有反应。


更新 2

代码现在编译时出现 0 个警告,但仍然对手势没有响应。


我根据 here 列出的四点(即 userInteractionEnabledminimumPressDurationnumberOfTapsRequirednumberOfTouchesRequired) 并确保在 UIViewController.h.

中指定委托

我最初的第一个问题已经得到解答

Q.1接口a中的协议定义如何 duplicate ?

这两个问题还有待解答

Q.2 如果默认情况下 UIGestureRecognizer 协议已经存在,那么如何定义将处理手势消息的目标?或者

Q.3 如何定义一个不是 self 而是 ViewController 中的方法的委托目标?

我相信有更多经验的人可以识别答案并解释我没有做的事情或提出问题以更清楚地说明问题。感谢期待。

图文并茂的解释也会让那些在 Objective C 工作的人受益,他们需要更多地了解代表——对某些人来说是旧知识,但对于试图赶上进度的黑客(比如我 :-) 来说仍然是一个前沿领域。

格雷格


更新 2

如果从 handleTap: 手势声明中删除 .delegate 属性 并点击红色方块,程序将崩溃并显示以下日志:

[OneOfSeveralSubviews handleTapSelect:] : unrecognized selector sent to instance 0x7fbe27d064b0

如果 .delegate 属性 也从 handleLongPress:handlePan: 手势声明中删除,则会出现类似的崩溃日志。


代码的第一部分是ViewController(下方),其中包含三个目标方法(1) handleLongPress: (2) handleTapSelect:(3) handlePan:

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

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

()

- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
    {
        NSLog(@"started");
        self.timer=[NSTimer scheduledTimerWithTimeInterval:1.0
                                                    target:self
                                                  selector:@selector(stillPressing:)
                                                  userInfo:nil
                                                   repeats:YES];
    } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
    {
        [self.timer invalidate];
        self.timer = nil;
        NSLog(@"ended");
    }
}

    - (void)stillPressing:(NSTimer *)timer
    {
        NSLog(@"pressing");
    }

(方法二)

- (void)handleTapSelect:(id)sender
{
    NSLog(@"tapped");
}

(method 3)

 - (void)handlePan:(UIPanGestureRecognizer*)gestureRecognizer
{
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    UIView *piece = [gestureRecognizer view];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
        CGPoint translation = [gestureRecognizer translationInView:[piece superview]];

        [piece setCenter:CGPointMake([piece center].x + translation.x, [piece center].y + translation.y)];
        [gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];

        NSLog(@"%f %f", translation.x, translation.y);

        [UIView animateWithDuration:0.75
                              delay:0
             usingSpringWithDamping:0.75
              initialSpringVelocity:0
                            options:UIViewAnimationOptionCurveLinear
                         animations:^{

                          piece.frame = touchFrame;
                      }
                            completion:^(BOOL finished) {
                     }];
    }
}


- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        UIView *piece = gestureRecognizer.view;
        CGPoint locationInView = [gestureRecognizer locationInView:piece];
        CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];

        piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
        piece.center = locationInSuperview;
    }
}

ViewController.h

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

@interface ViewController : UIViewController <FirstSubviewGestureDelegate, SecondSubviewGestureDelegate>
{
    CGRect touchFrame;
}

@property (strong, nonatomic) NSTimer *timer;

@end

OneOfSeveralSubviews.m

#import "OneOfSeveralSubviews.h"

@implementation OneOfSeveralSubviews

- (id)initView:(CGRect)rect
{
    self = [super initWithFrame:rect];
    if (self)
    {
        CGFloat width = [UIScreen mainScreen].bounds.size.width;
        CGFloat height = [UIScreen mainScreen].bounds.size.height;
        CGPoint screenCentre = CGPointMake(width*0.5, height*0.5);

        CGFloat fullSide = width * 0.33;
        CGFloat halfSide = fullSide * 0.5;

        touchFrame = CGRectMake(screenCentre.x - halfSide, screenCentre.y - halfSide, fullSide, fullSide);
        UIView *hotspot = [[UIView alloc] initWithFrame:touchFrame];
        hotspot.backgroundColor = [UIColor redColor];

        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];

        UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:(id)self.delegate action:@selector(handleTapSelect:)];
        [tapGR setDelegate:(id)self.delegate];
        [tapGR setNumberOfTapsRequired:1];
        [tapGR setNumberOfTouchesRequired:1];
        [hotspot addGestureRecognizer:tapGR];
        [self addSubview:hotspot];

        UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:(id)self.delegate action:@selector(handlePan:)];
        [panGR setDelegate:(id)self.delegate];
        [panGR setMinimumNumberOfTouches:1];
        [panGR setMaximumNumberOfTouches:1];
        [hotspot addGestureRecognizer:panGR];

        self.userInteractionEnabled = YES;
    }
    return self;
}

@end

OneOfSeveralSubviews.h

#import <UIKit/UIKit.h>

@protocol FirstSubviewGestureDelegate <NSObject>

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

@end

@interface OneOfSeveralSubviews : UIView
{
    CGRect touchFrame;
}

- (id)initView:(CGRect)rect;

@property (assign) id<FirstSubviewGestureDelegate> delegate;

@end

链接

可能重复

handling gestures includes examples in Swift. If you work in Objective C refer to Touches 上的 Apple 文档,但请记住,它不再在“早于 iOS7”的版本上编译。如果您能够为 Objective C 程序员提供更有用的参考,请编辑此注释。

UIGestureRecognizerDelegate 由 UIKit 声明。您不能创建自己的名为 UIGestureRecognizerDelegate 的协议;这是一个相互矛盾的声明。

按照惯例,类 和前缀为 UI 的协议由 UIKit 声明,您不应声明自己的对象和类 加上这个前缀。使用像 MyGestureRecognizerDelegate

这样的东西