ios - 如果忽略“UIGestureRecognizerDelegate”的重复协议(protocol)定义,如何定义目标

标签 ios objective-c delegates uigesturerecognizer

更新2

即使问题仍然存在,当前形式的问题也已得到回答和接受。该代码现在以0警告进行编译,但仍然对手势无响应。解决问题后,将希望通过准备新问题的过程来更新代码。一个新问题已发布here

据我所知,在我所阅读的任何帖子中都从未问过或回答过这个问题(请参阅下面的重复内容)。

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

最终,我想将手势消息从多个子类的UIViews发送到UIViewController中的常见处理程序,但是在尝试执行此操作时遇到了问题。在编写代码时,我研究了有关使用UIGestureRecognition的委托以及Touchs中的Objective C方法(请参阅下面的注释)和SO帖子中的示例(下面的链接)一起使用的Apple文档。

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

  • 重复协议

  • “UIGestureRecognizerDelegate”的重复协议定义为
    被忽略


    更新1

    现在已经解决了这一问题。 Paul’s answer阐明了到目前为止我还不了解的一点。作为回应,我在本文中更改了协议的名称,测试了代码并对其进行了更新。

    OneOfSeveralSubviews.h中,该协议现在称为FirstGestureRecognizerDelegate.。已在ViewController中进行了相关更改,例如
    @interface ViewController : UIViewController <FirstSubviewGestureDelegate, SecondSubviewGestureDelegate>
    

  • 未声明的选择器。

  • 通过将委托属性键入(即,插入id(建议为here)),对三个手势声明(即initWithTarget:(id)self)进行了类似的更改,并在每个self实例中添加了一个委托属性,从而将三个警告静音了,从而将消息发送到预期的目标-即(id)self.delegate而不是(id)self
    该代码先前编译时带有一个警告,但对手势没有任何响应。

    更新2

    该代码现在以0警告进行编译,但仍然对手势无响应。

    我对照here列出的四个要点(即userInteractionEnabledminimumPressDurationnumberOfTapsRequirednumberOfTouchesRequired)检查了代码,并确保在UIViewController.h.中指定委托

    我的第一个问题已经回答

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

    这两个问题有待回答

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

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

    我相信,有更多经验的人可以认出答案,并解释我还没有做的事情,或者提出一些可以使问题更加清晰的问题。谢谢您的期待。

    对于需要在 objective-c 中工作的人,他们需要更多地了解代表-一些人的过往知识,但仍然是试图追赶的黑手(像我一样:-)的前沿领域,这对图例的解释也会有所帮助。

    格雷格

    更新2

    如果从.delegate手势声明中删除了handleTap:属性,并且点击了红色方块,则程序将崩溃,并显示以下日志:
    [OneOfSeveralSubviews handleTapSelect:] : unrecognized selector sent to instance 0x7fbe27d064b0
    如果还从.delegatehandleLongPress:手势声明中删除了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];    
    }
    

    (method 1)
    - (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");
        }
    

    (方法2)
    - (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
    

    链接
  • What is meant by .delegate=self?
  • What are the differences between delegates and events ?
  • Why are Objective-C delegates usually given the property assign instead of retain?
  • when to use respondsToSelector in objective-c
  • Objective C responds to selector
  • iOS - UILongPressGestureRecognizer
  • Using UILongPressGestureRecognizer and UISwipeGestureRecognizer
  • Using UILongPressGestureRecognizer For Subviews of UIScrollview

  • 可能重复的
  • Duplicate protocol definition warning, but I need multiples of this
    protocol
  • warning: duplicate protocol definition of '…' is ignored
  • Duplicate protocol definition
  • Duplicate protocol definition warning
  • Handling app delegates and switching between views

  • 注意

    关于handling gestures的Apple文档包括Swift中的示例。如果您在Objective C中工作,请参考Touches,但请记住,它不再在“早于iOS 7”的版本上编译。如果您能够为Objective C程序员提供更有用的参考,请编辑此注释。

    最佳答案

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

    按照约定,带有UI前缀的类和协议由UIKit声明,并且您不应使用此前缀声明自己的对象和类。使用类似MyGestureRecognizerDelegate的东西

    关于ios - 如果忽略“UIGestureRecognizerDelegate”的重复协议(protocol)定义,如何定义目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49246176/

    相关文章:

    ios - APNS - 将应用程序从生产中转移到开发中

    iphone - 通过方向更改获取屏幕宽度/高度的正确方法是什么?

    ios - 转到另一个 Viewcontroller

    iphone - 将核心动画与 CALayers 以外的对象一起使用

    proxy - 如何使用 dart 实现委托(delegate)/代理?

    Javascript 委托(delegate)问题

    ios - 存储 UISwitch 状态的问题

    ios - 在 Swift 3 中获取 Google Drive iOS 基本目录中的文件夹列表?

    ios - iPhone 5 上不同宽度的按钮

    c# - 在这种情况下我将如何使用委托(delegate)?