基于位置的 UIGestureRecognizer

Posted

技术标签:

【中文标题】基于位置的 UIGestureRecognizer【英文标题】:Location based UIGestureRecognizers 【发布时间】:2014-01-04 22:22:56 【问题描述】:

我正在开发一项功能,它允许 ios 用户滑动屏幕的左半部分并触发一个方法。 UISwipeGestureRecognizers 在 ViewController.m 文件中被调用,这些识别器选择的方法在 MyScene.m 中。

我可以在没有滑动位置设置的情况下让它工作,但我还没有找到一种成功的方法让它只在屏幕的左半部分触发。我在下面包含了一些代码,显示了有无位置要求的示例。

ViewController.m:

- (void)viewDidLayoutSubviews

[super viewDidLayoutSubviews];
    SKView * skView = (SKView *)self.view;
    if (!skView.scene) 
        skView.showsFPS = YES;
        skView.showsNodeCount = YES;

        SKScene *scene = [MyScene sceneWithSize:skView.bounds.size];
        scene.scaleMode = SKSceneScaleModeAspectFill;
        [skView presentScene:scene];

        UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:(scene) action:@selector(screenSwipedRight)];
        swipeRight.numberOfTouchesRequired = 1;
        swipeRight.direction=UISwipeGestureRecognizerDirectionRight;
        [self.view addGestureRecognizer:(swipeRight)];

        UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:(scene) action:@selector(screenSwipedLeft)];
        swipeLeft.numberOfTouchesRequired = 1;
        swipeLeft.direction=UISwipeGestureRecognizerDirectionLeft;
        [self.view addGestureRecognizer:(swipeLeft)];

        UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:(scene) action:@selector(screenSwipedUp)];
        swipeUp.numberOfTouchesRequired = 1;
        swipeUp.direction=UISwipeGestureRecognizerDirectionUp;
        [self.view addGestureRecognizer:(swipeUp)];
    

MyScene.m:

-(void)screenSwipedRight:(UISwipeGestureRecognizer *)swipedRight

    CGPoint touchPoint = [swipedRight locationInView:(self.view)];
    NSInteger movePlayer;
    if (touchPoint.x <=self.view.bounds.size.width/2) 
        movePlayer = 1;
     else 
        movePlayer = 2;
    
    if (movePlayer ==1) 
        CGFloat percentToRight = 1-(self.playerOne.position.x / self.view.bounds.size.width);
        NSTimeInterval timeToRight = self.horizontalRunSpeed * percentToRight;
        NSLog(@"Percent to right = %f",percentToRight);
        NSLog(@"Time to right = %f",timeToRight);
        SKAction *moveNodeRight = [SKAction moveToX:self.view.bounds.size.width-self.playerOne.size.width duration:timeToRight];
        [self.playerOne runAction:[SKAction sequence:@[moveNodeRight]]];
    


-(void)screenSwipedLeft

    NSLog(@"Screen was swiped to the left");
    CGFloat percentToLeft = self.playerOne.position.x / self.view.bounds.size.width;
    NSTimeInterval timeToLeft = self.horizontalRunSpeed * percentToLeft;
    NSLog(@"Percent to left = %f",percentToLeft);
    NSLog(@"Time to left = %f",timeToLeft);
    SKAction *moveNodeLeft = [SKAction moveToX:self.playerOne.size.width duration:timeToLeft];
    [self.playerOne runAction:[SKAction sequence:@[moveNodeLeft]]];


-(void)screenSwipedUp

    NSLog(@"Screen was swiped up");

    [self runAction:[SKAction sequence:@[[SKAction runBlock:^ self.physicsWorld.gravity = self.antiGravityAmount;],[SKAction waitForDuration:.25],[SKAction runBlock:^ self.physicsWorld.gravity = self.gravityAmount;]]]];

swipedRight 方法是我试图区分滑动位置的地方。

执行此代码会导致信号 SIGABRT 错误,但仅当我向右滑动时。向左或向上滑动继续正常工作。这可能与从“locationInView”中选择视图有关,但我可能完全错了。

有人知道怎么做吗?

感谢您的帮助。

编辑:这里是关于错误的日志文件-

2014-01-04 18:10:32.316 Romp[584:70b] 找不到 CFBundle 0x976afe0 的可执行文件(未加载)

2014-01-04 18:10:32.375 Romp[584:70b] viewDidLoad 已运行

2014-01-04 18:10:32.425 嬉戏[584:70b] 尺寸:480, 320

2014-01-04 18:10:32.427 Romp[584:70b] 屏幕已初始化

2014-01-04 18:10:33.917 Romp[584:70b] -[MyScene screenSwipedRight]:无法识别的选择器发送到实例 0x9995790

2014-01-04 18:10:33.920 Romp[584:70b] * 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[MyScene screenSwipedRight]:无法识别的选择器发送到实例 0x9995790'

* 首先抛出调用栈:

( 0 CoreFoundation 0x0185e5e4 异常预处理 + 180 1 libobjc.A.dylib 0x015e18b6 objc_exception_throw + 44 2核心基础0x018fb903-[NSObject(NSObject)不识别选择器:]+275 3 CoreFoundation 0x0184e90b __转发 + 1019 4 核心基础 0x0184e4ee _CF_forwarding_prep_0 + 14 5 UIKit 0x005a8e8c _UIGestureRecognizerSendActions + 230 6 UIKit 0x005a7b00-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 383 7 UIKit 0x005a956d-[UIGestureRecognizer _delayedUpdateGesture] + 60 8 UIKit 0x005acacd _UIGestureRecognizerUpdate_block_invoke + 57 9 UIKit 0x005aca4e _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 317 10 UIKit 0x005a3148 _UIGestureRecognizerUpdate + 199 11 UIKit 0x0026f19a-[UIWindow_sendGesturesForEvent:] + 1291 12 UIKit 0x002700ba-[UIWindow 发送事件:] + 1030 13 UIKit 0x00243e86 -[UIApplication 发送事件:] + 242 14 UIKit 0x0022e18f _UIApplicationHandleEventQueue + 11421 15 核心基础 0x017e783f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 15 16 核心基础 0x017e71cb __CFRunLoopDoSources0 + 235 17 核心基础 0x0180429e __CFRunLoopRun + 910 18 核心基础 0x01803ac3 CFRunLoopRunSpecific + 467 19 核心基础 0x018038db CFRunLoopRunInMode + 123 20 图形服务 0x038039e2 GSEventRunModal + 192 21 图形服务 0x03803809 GSEventRun + 104 22 UIKit 0x00230d3b UIApplicationMain + 1225 23 嬉戏 0x0000615d 主要 + 141 24 libdyld.dylib 0x01e9c70d 开始 + 1 25 ??? 0x00000001 0x0 + 1 )

libc++abi.dylib:以 NSException 类型的未捕获异常终止 (lldb)

【问题讨论】:

错误到底发生在哪一行? 线程 1 队列:com.apple.main-thread.... @autoreleasepool return UIApplicationMain (argc, argv, nil, NSStringFromClass [AppDelegate] 类。将日志文件添加到我的帖子中以获取更多信息信息。 据我了解,问题是您试图通过键入 self.view 在方法中获取 MyScene 的视图。相反,您应该使用 swipeRight.view 更改为 swipedRight.view 导致同样的错误。 【参考方案1】:
'-[MyScene screenSwipedRight]: unrecognized selector sent to instance 0x9995790'

相当标准的错误。你这样做:

 UISwipeGestureRecognizer *swipeRight =
     [[UISwipeGestureRecognizer alloc] initWithTarget:(scene) 
                                               action:@selector(screenSwipedRight)];

您将@selector(screenSwipedRight) 注册为回调,这是一个不带参数的方法。您的代码中不存在此方法。

您的方法具有相同的名称,但它需要一个额外的参数UISwipeGestureRecognizer*,这使得它成为一个不同的方法。所以需要注册为@selector(screenSwipedRight:)。注意末尾的冒号。

PS:在您的应用中启用exception breakpoint。当发生类似这样的异常时,这将使 Xcode 向您显示代码行。无需进行大量猜测即可进行调试。

【讨论】:

这很好用并且解释得很好。感谢您抽出宝贵时间提供帮助!

以上是关于基于位置的 UIGestureRecognizer的主要内容,如果未能解决你的问题,请参考以下文章

UIGestureRecognizer 从头开始​​制作 UISlider

添加优先于所有其他交互的 UIGestureRecognizer

UIGestureRecognizer

UIGestureRecognizer

点击按钮时取消 UIGestureRecognizer?

UIGestureRecognizer 目标问题