如果忽略"UIGestureRecognizerDelegate"的重复协议定义,如何定义目标 [英] if Duplicate protocol definition of 'UIGestureRecognizerDelegate' is ignored how can I define targets

查看:79
本文介绍了如果忽略"UIGestureRecognizerDelegate"的重复协议定义,如何定义目标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新2

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

The question in its current form has been answered and accepted even though a problem remains viz. the code now compiles with 0 warnings but still remains unresponsive to gestures. Code will be updated once the problem is solved, hopefully, through the process of preparing a new question. A new question has been posted here.

据我所知,在我读过的任何一篇文章中都从未问过或回答过这个问题(请参见下面的 重复项).

As far as I know this question has never been asked or answered in any post I have read (see possible duplicates below).

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

I am trying to write Objective C test code to send either long press, tap or pan messages from any area defined by a rectangular UIView on an iPhone screen. So far I can send discrete or continuous messages reliably using either UILongPressGesture, UITapGesture or UIPanGesture if both UIView and handler methods are located in the UIViewController.

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

Ultimately I want to send gesture messages from several subclassed UIViews to common handlers in the UIViewControllerbut I hit problems when I tried to do it. While writing the code I studied an Apple document on using delegates for UIGestureRecognition together with Objective C methods in Touches (see Note below) and examples found in SO posts (Links below).

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

The code fails to respond to gestural input. Initially it compiled with four warnings and two issues:

  1. 重复协议

"UIGestureRecognizerDelegate"的重复协议定义为 已忽略

Duplicate protocol definition of 'UIGestureRecognizerDelegate' is ignored


更新1

现在已解决此问题. Paul的答案阐明了到目前为止我还不了解的观点.作为回应,我在本文中更改了协议的名称,测试了代码并对其进行了更新.

This has now been addressed. Paul’s answer clarifies a point I hadn’t understood until now. In response I changed the name of the protocol, tested the code and updated it in this post.

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

In OneOfSeveralSubviews.h the protocol is now called FirstGestureRecognizerDelegate. Relevant changes have been made in the ViewController e.g.

@interface ViewController : UIViewController <FirstSubviewGestureDelegate, SecondSubviewGestureDelegate>


  1. 未声明的选择器.

通过设置代表属性来静音三个警告-即插入id(根据建议插入 here )-对三个手势声明(即initWithTarget:(id)self)进行了类似的更改,并在self的每个实例中添加了一个委托属性,以便将消息发送到预期的目标-即(id)self.delegate代替(id)self

Three warnings were silenced by making the delegate property typed - i.e. inserting id (as recommended here) - with similar changes made to the three gesture declarations - i.e. initWithTarget:(id)self - with a delegate property added to each instance of self so messages are sent to intended targets - i.e. (id)self.delegate instead of (id)self

该代码先前编译时带有一个警告,但对手势无响应.

The code previously compiled with one warning but remained unresponsive to gestures.

更新2

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

The code now compiles with 0 warnings but still remains unresponsive to gestures.

我对照列出的四个点检查了代码 此处 (即userInteractionEnabledminimumPressDurationnumberOfTapsRequirednumberOfTouchesRequired),并确保在UIViewController.h.

I checked the code against the four points listed here (i.e. userInteractionEnabled, minimumPressDuration, numberOfTapsRequired and numberOfTouchesRequired) and made sure to specify the delegate in UIViewController.h.

我的第一个初始问题已经回答

The first of my initial questions has already been answered

Q.1接口中的协议定义是duplicate吗?

这两个问题有待回答

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

Q.2 if the UIGestureRecognizer protocol is already there by default, then how do I define the targets that will handle the gesture messages ? or

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

Q.3 how do I define a delegate target that is not self but rather a method within the ViewController ?

我相信,有更多经验的人可以认出答案并解释我未做的事情,或者提出一些问题的答案,以进一步阐明问题.谢谢您的期待.

I'm confident someone with more experience can recognise the answers and explain what I haven't done or suggest questions that shed more light on the problem. Thanks in anticipation.

图文并茂的解释也将使那些需要学习更多有关委托人的知识的人受益,这需要对代理人有更多了解-有些人掌握了旧知识,但仍然赶不上黑客入侵的前沿领域(如我:-).

An illustrated explanation would also benefit those working in Objective C who need to learn more about delegates - old knowledge for some but still a frontier for hacks (like me :-) trying to catch up.

格雷格

更新2

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

If the .delegate property is removed from the handleTap: gesture declaration and the red square is tapped, the program will crash with the following log:

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

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

A similar crash log appears if the .delegate property is also removed from the handleLongPress: or handlePan: gesture declaration.

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

The first part of the code is the ViewController (below) which contains the three target methods called (1) handleLongPress: (2) handleTapSelect: and (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];    
}

(方法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");
}

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

链接

Links

  • 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

可能重复

possible duplicates

处理应用程序委托并在视图之间切换

注意

Note

处理手势包括Swift中的示例.如果您在Objective C中工作,请参考 iOS 7之前的版本"上编译.如果您能够为Objective C程序员提供更有用的参考,请编辑此注释.

The Apple document on handling gestures includes examples in Swift. If you work in Objective C refer to Touches but bear in mind that it no longer compiles on versions "earlier than iOS 7". If you are able to provide a more useful reference for Objective C programmers please edit this note.

推荐答案

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

UIGestureRecognizerDelegate is declared by UIKit. You can't create your own protocol named UIGestureRecognizerDelegate; it is a conflicting declaration.

按照惯例,以 UI 为前缀的类和协议由UIKit声明,并且您不应使用此前缀声明自己的对象和类.使用类似MyGestureRecognizerDelegate

By convention, classes and protocols prefixed with UI are declared by UIKit and you should not declare your own objects and classes with this prefix. Use something like MyGestureRecognizerDelegate

这篇关于如果忽略"UIGestureRecognizerDelegate"的重复协议定义,如何定义目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆