更新2
即使问题仍然存在,当前形式的问题也已得到回答和接受。该代码现在以0警告进行编译,但仍然对手势无响应。解决问题后,将希望通过准备新问题的过程来更新代码。一个新问题已发布here。
据我所知,在我所阅读的任何帖子中都从未问过或回答过这个问题(请参阅下面的重复内容)。
我正在尝试编写Objective C测试代码,以从iPhone屏幕上由矩形UIView
定义的任何区域中长按,点击或移动消息。到目前为止,如果UILongPressGesture,
和handler方法都位于UITapGesture
中,则我可以使用UIPanGesture
UIView
或UIViewController
可靠地发送离散或连续消息。
最终,我想将手势消息从多个子类的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列出的四个要点(即
userInteractionEnabled
,minimumPressDuration
,numberOfTapsRequired
和numberOfTouchesRequired
)检查了代码,并确保在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
如果还从
.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];
}
(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
链接
可能重复的
protocol
注意
关于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/