iOS Objective C - 使用长按创建视图/在相同的 UIView 上使用多个手势

iOS Objective C - Creating UIViews with LongPress / Using multiple gestures on same UIViews

对于作业,我必须创建一个满足以下条件的应用程序:

  1. 模拟等质量球的弹性碰撞
  2. 使用根视图作为竞技场来反弹球。 一种。根视图通过放置一个新球来响应长按。新球可以是静止的或具有初始速度。 b.竞技场应该有一些摩擦力来减慢任何移动的球。
  3. 双击一个球将其删除
  4. 您可以按住一个球,拖动以重新定位,并通过快速拖动和释放来轻弹它
  5. 球应该始终在场地内,即它在到达边缘时弹回。
  6. 球不应重叠。也就是说,您实现了相当不错的碰撞处理。

我相信我已经充分实施了 1、2b、5 和 6。如果有人可以帮助我理解如何实施其余部分,那就太好了,但现在我的主要问题如下:

2a。我希望能够通过长按屏幕来创建一个球。然后球应该出现在长按的位置。当只有一个球并且没有其他手势识别器时,我能够使它工作。

自从我实现了 tapGestureRecognzier 之后,长按识别器就不再有效了。我的应用程序运行,但只显示一个空白屏幕。似乎没有任何形式的接触被记录下来。没有球出现,但应用程序没有向我显示任何错误。

因此,我认为手势识别器要么相互干扰,要么设置不当。

我想要的是长按创建一个球,随后每次长按都会在按下位置创建一个不同颜色的球。然后双击一个球将从屏幕上移除该球,这样它就不再与其他球相互作用。

这是我目前完成的代码:

ViewController.h

 #import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UICollisionBehaviorDelegate, UIGestureRecognizerDelegate>

@end

ViewController.m

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()

@property (nonatomic, strong) UILongPressGestureRecognizer *longPressRecog;
@property (nonatomic, strong) UITapGestureRecognizer *tapRecog;
@property (nonatomic, strong) UIDynamicAnimator *anim;
@property (nonatomic, strong) UIView *orangeBall, *blueBall, *redBall, *greenBall, *blackBall;
@property (nonatomic) CGPoint ballCenter;
@property (nonatomic) int numOfBalls;

-(void)physics;
-(void)createBall;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //Init Variables
    _numOfBalls = 0;

    // Prepare to handle Long Press to create ball object
    UILongPressGestureRecognizer *longPressRecog = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    self.longPressRecog.minimumPressDuration = 1.0f;
    [longPressRecog setDelegate:self];

    [self.view addGestureRecognizer:longPressRecog];

    // Handle Double Tap to delete ball
    UITapGestureRecognizer *tapRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
    [tapRecog setNumberOfTapsRequired:2];
    [tapRecog setDelegate:self];
    [self.orangeBall addGestureRecognizer:tapRecog];
    [self.blueBall addGestureRecognizer:tapRecog];
    //[self.redBall addGestureRecognizer:tapRecog];
    //[self.greenBall addGestureRecognizer:tapRecog];
    //[self.blackBall addGestureRecognizer:tapRecog];
}

// Handles Long Presses and creates a ball within the view
- (void)longPress:(UILongPressGestureRecognizer *)sender {
    if ([sender isEqual:self.longPressRecog]) {
        if (sender.state == UIGestureRecognizerStateBegan) {
            [self createBall];
        }
    }
}

// Set Ball Attributes
- (void)setOrangeBall {
    // Load ball view to screen
    self.orangeBall = [[UIView alloc] initWithFrame:CGRectMake(100.0, 100.0, 50.0, 50.0)];
    self.orangeBall.layer.cornerRadius = 25.0;
    self.orangeBall.backgroundColor = [UIColor orangeColor];
    self.orangeBall.layer.borderColor = [UIColor orangeColor].CGColor;
    self.orangeBall.layer.borderWidth = 0.0;
    //self.ballCenter = position;
    [self.view addSubview:self.orangeBall];

}

- (void)setBlueBall {
    // Load ball view to screen
    self.blueBall = [[UIView alloc] initWithFrame:CGRectMake(100.0, 100.0, 50.0, 50.0)];
    self.blueBall.layer.cornerRadius = 25.0;
    self.blueBall.backgroundColor = [UIColor blueColor];
    self.blueBall.layer.borderColor = [UIColor blueColor].CGColor;
    self.blueBall.layer.borderWidth = 0.0;
    //self.ballCenter = position;
    [self.view addSubview:self.blueBall];
}


// Create Balls
- (void)createBall {
    if (_numOfBalls == 0) {
        [self setOrangeBall];
        _numOfBalls += 1;
    } else if (_numOfBalls == 1) {
        [self setBlueBall];
        _numOfBalls += 1;
    }

    // Begin animations
    self.anim = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

    // Init Gravity
    [self physics];
}

// Delete Balls
- (void)deleteBall {
    [self.view removeFromSuperview];
}

// Gravity
- (void)physics {
    // Collision Behavior -- Defines boundaries of view within which the ball must stay. If the ball hits a boundary, it will bounce off it.
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.orangeBall, self.blueBall, self.redBall, self.greenBall, self.blackBall]];
    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;

    [collisionBehavior addBoundaryWithIdentifier:@"TopOfView"
                                       fromPoint:CGPointMake(0., -self.view.bounds.size.height)
                                         toPoint:CGPointMake(self.view.bounds.size.width, -self.view.bounds.size.height)];
    [collisionBehavior addBoundaryWithIdentifier:@"BottomOfView"
                                       fromPoint:CGPointMake(0., self.view.bounds.size.height)
                                         toPoint:CGPointMake(self.view.bounds.size.width, self.view.bounds.size.height)];
    [collisionBehavior addBoundaryWithIdentifier:@"LeftOfView"
                                       fromPoint:CGPointMake(0., -self.view.bounds.size.height)
                                         toPoint:CGPointMake(0., self.view.bounds.size.height)];
    [collisionBehavior addBoundaryWithIdentifier:@"RightOfView"
                                       fromPoint:CGPointMake(self.view.bounds.size.width, -self.view.bounds.size.height)
                                         toPoint:CGPointMake(self.view.bounds.size.width, self.view.bounds.size.height)];

    collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
    collisionBehavior.collisionDelegate = self;
    [self.anim addBehavior:collisionBehavior];


    // Ball's physical atributes -- Determines how ball behaves such as its elasticity, amount of friction, collision behavior, etc.
    UIDynamicItemBehavior *ballPhysics = [[UIDynamicItemBehavior alloc] initWithItems:@[self.orangeBall, self.blueBall, self.redBall, self.greenBall, self.blackBall]];
    ballPhysics.elasticity = 0.80;
    ballPhysics.resistance = 0.50;
    ballPhysics.friction = 0.50;
    ballPhysics.allowsRotation = NO;
    [self.anim addBehavior:ballPhysics];
}

-(void)tapped:(UITapGestureRecognizer *)recognizer {
    [self deleteBall];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

眼前的问题是您在局部范围内声明 longPressRecog

UILongPressGestureRecognizer *longPressRecog = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

但是针对 class 级别对象进行测试,这是一个不同的对象:

if ([sender isEqual:self.longPressRecog])

此测试失败。

您可以通过实例化 class 级别对象而不是局部范围的对象来解决此问题:

self.longPressRecog = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

这会导致您发现代码的其他问题,但您可以看到手势识别器本身没有问题。