iOS Objective C - 使用长按创建视图/在相同的 UIView 上使用多个手势
iOS Objective C - Creating UIViews with LongPress / Using multiple gestures on same UIViews
对于作业,我必须创建一个满足以下条件的应用程序:
- 模拟等质量球的弹性碰撞
- 使用根视图作为竞技场来反弹球。
一种。根视图通过放置一个新球来响应长按。新球可以是静止的或具有初始速度。
b.竞技场应该有一些摩擦力来减慢任何移动的球。
- 双击一个球将其删除
- 您可以按住一个球,拖动以重新定位,并通过快速拖动和释放来轻弹它
- 球应该始终在场地内,即它在到达边缘时弹回。
- 球不应重叠。也就是说,您实现了相当不错的碰撞处理。
我相信我已经充分实施了 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:)];
这会导致您发现代码的其他问题,但您可以看到手势识别器本身没有问题。
对于作业,我必须创建一个满足以下条件的应用程序:
- 模拟等质量球的弹性碰撞
- 使用根视图作为竞技场来反弹球。 一种。根视图通过放置一个新球来响应长按。新球可以是静止的或具有初始速度。 b.竞技场应该有一些摩擦力来减慢任何移动的球。
- 双击一个球将其删除
- 您可以按住一个球,拖动以重新定位,并通过快速拖动和释放来轻弹它
- 球应该始终在场地内,即它在到达边缘时弹回。
- 球不应重叠。也就是说,您实现了相当不错的碰撞处理。
我相信我已经充分实施了 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:)];
这会导致您发现代码的其他问题,但您可以看到手势识别器本身没有问题。