如何使用 Interface Builder 设置 UIScreenEdgePanGestureRecognizer?

Posted

技术标签:

【中文标题】如何使用 Interface Builder 设置 UIScreenEdgePanGestureRecognizer?【英文标题】:How do I set up an UIScreenEdgePanGestureRecognizer using Interface Builder? 【发布时间】:2014-10-08 12:32:12 【问题描述】:

当我使用 Interface Builder 将 UIScreenEdgePanGestureRecognizer 添加到我的视图控制器时,我无法让 UIScreenEdgePanGestureRecognizer 工作,所以我在这里询问我是否做错了什么或者是否存在错误Xcode。

以下是重现的步骤:

使用适用于 ios 的“单一视图应用程序”模板创建一个新的 Xcode 项目。 通过从 Interface Builder 的对象库中拖动一个 UIView 到主视图控制器中 通过从 Interface Builder 的对象库中拖动一个 UIScreenEdgePanGestureRecognizer 到视图中 确保已启用手势识别器并选择边缘:

打开ViewController 类的助手编辑器,然后按住Ctrl 键从UIScreenEdgePanGestureRecognizer 拖动到ViewController 的实现块以创建一个新的IBAction ` 在动作的方法体中添加一个断点来测试边缘平移手势是否被识别

生成的代码如下:

如果我在我的设备(运行 iOS 8.02 的 iPhone 6)上运行应用程序,当我进行边缘滑动时断点不会被命中。

我有什么遗漏吗?

更新:这是在 2014 年 10 月 8 日向 Apple (rdar://18582306) 提交的错误,但在 Xcode 6.4 (6E35b) 中仍未解决

【问题讨论】:

【参考方案1】:

我设置了一个项目来测试您的问题,并发现了与您相同的问题。以下是我设置的测试场景:

我完全按照你的做法使用 Interface Builder 来构建屏幕边缘手势。我的代码中唯一的区别是我在选择器中放了一行代码,这样调试器就会停下来。调试器未能完全按照您的发现停止。

-(void)handlePan:(id)sender

    NSString *test = @"";

然后,我使用 Interface Builder 在同一视图上使用捏合手势创建了一个额外的手势,并且我能够让调试器在该选择器内停止。所以 Interface Builder 似乎能够正确构建其他手势。

然后我使用以下代码手动创建了屏幕边缘手势,它按预期工作。

在 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 实现似乎有问题。

【讨论】:

想补充一点,我在模拟器和我的设备上对此进行了测试,结果相同 - 对 IB 实现的手势没有响应。 感谢您花时间对此进行测试。我现在已经向 Apple 提交了错误报告:openradar.io/18582306 我已将此标记为已接受的答案,因为它确认我没有做任何不正确的事情,并且 Xcode 的行为不符合预期。 @zisoft 我正在使用 6.0.1 (6A317) 这里不需要设置委托..有吗?【参考方案2】:

我已经在 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得到一个错误

【讨论】:

【参考方案3】:

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

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

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

这个要求只适用于UIScreenEdgePanGestureRecognizer,所以我认为这就是Xcode出错的原因,它必须按照正常的顺序来实现,alloc->init->attach->set value。它适用于所有其他 GestureRecongnizer,但不适用于 UIScreenEdgePanGestureRecognizer。

【讨论】:

你引用的那一行是指作者已经在截图中设置的边缘值(上、左、右、下)【参考方案4】:

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)")

【讨论】:

【参考方案5】:

要确保多个手势识别器可以协同工作,您必须实现方法shouldRecognizeSimultaneouslyWithGestureRecognizer 并返回true:

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

对不起,Swift 代码,但你应该明白了。

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

【讨论】:

不幸的是,实现gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 委托方法并使ViewController 成为UIScreenEdgePanGestureRecognizer 的委托没有任何区别。仍然没有检测到边缘平移。常规 UIPanGestureRecognizer 工作正常。认为我可能会提出错误报告。【参考方案6】:

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

虽然 IB 中有边缘复选框,但它们似乎被忽略了。

我是这样解决的: 按住 Ctrl 键从手势识别器拖动到 viewController 类以创建 IBOutlet:

class ViewController: UIViewController 
    @IBOutlet var leftEdgeGestureRecognizer: UIScreenEdgePanGestureRecognizer!

然后,在 viewDidLoad 中:

leftEdgeGestureRecognizer.edges = .Left

最后,从识别器中按住 ctrl 并拖动以创建 IBAction

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

【讨论】:

【参考方案7】:

长期面临同样的问题。它是一个 xcode 错误,最好以编程方式添加它。

【讨论】:

以上是关于如何使用 Interface Builder 设置 UIScreenEdgePanGestureRecognizer?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Interface Builder 中使用自定义 UIButton 类别?

如何在 Xcode 9 中将 Autoresizing 应用于 Interface Builder?

Interface Builder 是如何知道 UIViewController 的视图的?

如何在 Interface Builder 中获取 iPhone,而不是 iPad 视图

Interface Builder 将控制出口设置为零——为啥?

如何在 Interface Builder 中的 UIViewController 中自动调整 UIView Outlet 的大小