如何使用Interface Builder设置UIScreenEdgePanGestureRecognizer?

当我使用Interface Builder将其添加到视图控制器时,我无法使UIScreenEdgePanGestureRecognizer正常工作,所以我在这里要求确定我是否做错了什么,或者是否存在Xcode中的错误。

以下是重现步骤:

  • 使用iOS的“单一视图应用程序”模板创build一个新的Xcode项目。
  • 通过从Interface Builder中的对象库拖动一个UIView到主视图控制器
  • 从界面生成器中的对象库中拖出一个UIScreenEdgePanGestureRecognizer添加到视图
  • 确保手势识别器已启用,并且select了边缘:

在这里输入图像说明

  • 打开ViewController类的助手编辑器,并从UIScreenEdgePanGestureRecognizer拖动到ViewController的实现块来创build一个新的IBAction在动作的方法体中添加一个断点来testing边缘平移手势是否被识别

结果代码如下:

代码示例

如果我在我的设备上运行应用程序(运行iOS 8.02的iPhone 6),当我执行边缘滑动时,断点不会受到影响。

有什么我失踪?

更新:这是在2014年10月8日作为苹果(rdar:// 18582306)的bug提交的,仍然没有在Xcode 6.4(6E35b)中解决。

我build立了一个项目来testing你的问题,发现你所做的同样的问题。 以下是我设置要testing的场景:

  • 我使用界面生成器完全按照您的方式构build屏幕边缘手势。 我的代码唯一的区别是我把一行代码放在select器中,所以debugging器会停下来。 debugging器无法正常停止,因为你发现。

     -(void)handlePan:(id)sender { NSString *test = @""; } 
  • 然后,我使用Interface Builder在同一视图中使用捏手势创build了一个额外的手势,我可以让debugging器在该select器内暂停。 所以Interface Builder似乎能够正确地构build其他手势。

  • 然后我使用下面的代码手动创build了屏幕边缘手势,并按预期工作。

在ViewController.h文件中,我包含了UIGestureRecognizerDelegate。

 @interface ViewController : UIViewController <UIGestureRecognizerDelegate> @end 

在ViewController.m文件中,我手动实现了手势。

 #import "ViewController.h" @interface ViewController () -(void)handlePan:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [pan setEdges:UIRectEdgeLeft]; [pan setDelegate:self]; [self.view addGestureRecognizer:pan]; } -(void)handlePan:(id)sender { NSString *test = @""; } @end 

我最后得出的结论与你所做的一样 – Interface Builder的UIScreenEdgePanGestureRecognizer的实现似乎有些问题。

我已经在Xcode 7.0 Beta 4(7A165t)中试过了,它仍然是一个错误。 通过Interface Builder添加屏幕边缘泛姿态识别器不会调用引用的IBAction,但是像这样以编程方式添加它工作正常:

 class ViewController: UIViewController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() let edgeGestureRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: "userSwipedFromEdge:") edgeGestureRecognizer.edges = UIRectEdge.Left edgeGestureRecognizer.delegate = self self.view.addGestureRecognizer(edgeGestureRecognizer) } func userSwipedFromEdge(sender: UIScreenEdgePanGestureRecognizer) { if sender.edges == UIRectEdge.Left { print("It works!") } } } 

提示:不要忘记将UIGestureRecognizerDelegate协议添加到您的类中。 否则,你会在edgeGestureRecognizer.delegate = self得到一个错误

它可以被认为是一个错误,但实际上,这是有用的:

“在创build屏幕边缘平移手势识别器之后,在将手势识别器附加到视图之前,为边缘属性指定一个适当的值。

https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIScreenEdgePanGestureRecognizer_class/index.html

这个要求只适用于UIScreenEdgePanGestureRecognizer,所以我认为这就是为什么Xcode使它错了,它必须作为正常序列,alloc-> init-> attach->设置值来实现。 它将适用于所有其他的GestureRecongnizer,但不适用于UIScreenEdgePanGestureRecognizer。

为了确保多个手势识别器可以一起工作,您必须实现shouldRecognizeSimultaneouslyWithGestureRecognizer方法并返回true:

 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } 

对不起,斯威夫特代码,但你应该明白了。

即使您使用单个手势识别器,也必须实施此方法,因为视图可以具有自己的(系统)识别器,如MKMapView

Xcode并不总是一个好邻居。 抱歉。

 override func viewDidLoad() { super.viewDidLoad() let panGesture = UIScreenEdgePanGestureRecognizer(target: self, action: "panAction:") panGesture.edges = .Left view.addGestureRecognizer(panGesture) } func panAction(sender: UIScreenEdgePanGestureRecognizer) { let translation = sender.translationInView(sender.view!) println("Trans:\(translation)") } 

看来在Xcode 6.4的界面生成器和Swift中存在一个bug。 另外,Thomas LIU的回答也是正确的:似乎有必要在代码中设置.edge属性,而不是使用Interface Builder。

即使在IB有边缘checkbox,他们似乎被忽略。

我这样解决它:按住Ctrl键从手势识别器拖到viewController类来创build一个IBOutlet:

 class ViewController: UIViewController { @IBOutlet var leftEdgeGestureRecognizer: UIScreenEdgePanGestureRecognizer! 

那么在viewDidLoad中:

 leftEdgeGestureRecognizer.edges = .Left 

最后,从识别器中按住Ctrl键来创build一个IBAction

 @IBAction func swipeFromLeft(sender: AnyObject) { print("===> Swipe from left edge.\n") } 

面对同样的问题。 它的Xcode错误,它更好地以编程方式添加它。