I declared 2 IBActions "rightButtonPress" and "leftButtonPress" I linked them to 2 IBOutlets and ran a block of code in the IBactions:
-(void)leftButtonPress:(id)sender{
PlayerSprite.center = CGPointMake(PlayerSprite.center.x - 1, PlayerSprite.center.y);
}
-(void)rightButtonPress:(id)sender{
PlayerSprite.center = CGPointMake(PlayerSprite.center.x + 1, PlayerSprite.center.y);
}
and i also created 2 timers:
- (void)viewDidLoad
{
TouchLeftCheck = [NSTimer scheduledTimerWithTimeInterval:.01
target:self
selector:#selector(leftButtonPress:)
userInfo:nil
repeats:YES];
TouchRightCheck = [NSTimer scheduledTimerWithTimeInterval:.01
target:self
selector:#selector(rightButtonPress:)
userInfo:nil
repeats:YES];
BarrelEntrance = [NSTimer scheduledTimerWithTimeInterval:.01
target:self
selector:#selector(barrelStartDown)
userInfo:nil
repeats:YES];
[self frontBarrelAnimation];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
it all works well but when i linked it up to two IBObject Buttons something didn't work, when i linked my IBActions to my Objects(buttons), with "Touch Down" it didn't work. When i was in the ios simulator it only moved my object i time when i held and then it stopped, if you touch it again then the object moves one more time. But is there a link option that will allow me to make it do a smooth animation across the screen when i hold it down, and then stop when i let go? Thanks.
There are three components here:
A timer for animation
The start-touch event
The end-touch event
I recommend using an NSTimer to animate the view while the button is being pressed. This timer will be initialized and started when the button is pressed (touchDown:) and invalidated/nullified when the button is released (touchUpInside: and touchUpOutside:).
So to start off, bind the touch events to the button. (I assume that you are creating these buttons in interface builder, which is fine. If so, you can skip the initialization and just go straight to the addTarget: methods):
UIButton* leftButton = [[UIButton alloc] initWithFrame:...];
[leftButton addTarget:self action:#selector(startLeftAnimation) forControlEvents:UIControlEventTouchDown];
[leftButton addTarget:self action:#selector(stopAnimation) forControlEvents:UIControlEventTouchUpInside];
[leftButton addTarget:self action:#selector(stopAnimation) forControlEvents:UIControlEventTouchUpOutside];
Next, declare an instance variable timer:
#interface MyViewController
{
NSTimer* animationTimer;
}
Create the methods for the button events:
- (void)startLeftAnimation
{
animationTimer = [NSTimer scheduledTimerWithInterval: 0.02 target:self selector:#selector(animateLeft) userInfo:nil repeats:YES];
}
- (void)stopAnimation
{
if(animationTimer != nil)
{
[animationTimer invalidate];
animationTimer = nil;
}
}
Finally, create the animation method
- (void)animateLeft
{
PlayerSprite.center = CGPointMake(PlayerSprite.center.x - 1, PlayerSprite.center.y);
}
Rinse and repeat for the right button animation.
Related
I am currently building a custom keyboard and I am almost done. One problem that I have is with the delete button. When the user taps the delete button, it does what it should do and deletes the previous text entry. However when the user holds the button down, nothing happens. How do I make it so that when the user holds down the delete button, the keyboard continuously deletes like in the standard ios keyboard? This is my current code:
pragma mark Keyboards
- (void)addGesturesToKeyboard{
[self.keyboard.deleteKey addTarget:self action:#selector(pressDeleteKey)forControlEvents:UIControlEventTouchUpInside];
and:
-(void)pressDeleteKey{
[self.textDocumentProxy deleteBackward];
}
Thanks for your help.
Swift 3 Use "allowableMovement" property
override func viewDidLoad() {
super.viewDidLoad()
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(KeyboardViewController.handleLongPress(_:)))
longPress.minimumPressDuration = 0.5
longPress.numberOfTouchesRequired = 1
longPress.allowableMovement = 0.1
buttonDelete.addGestureRecognizer(longPress)
}
func handleLongPress(_ gestureRecognizer: UIGestureRecognizer) {
textDocumentProxy.deleteBackward()
}
you can do this by managing button’s events like touchdown, touchupinside and touchoutside.
When button press at that time start timer with delay of 0.2 seconds and delete last characters from textDocumentProxy until button’s touchup method will fire and after that you just need to invalidate timer.
[self.btnDelete addTarget:self action:#selector(btnTocuhDown:) forControlEvents:UIControlEventTouchDown];
[self.btnDelete addTarget:self action:#selector(btnTouchUp:) forControlEvents:UIControlEventTouchUpInside];
[self.btnDelete addTarget:self action:#selector(btnTouchUp:) forControlEvents:UIControlEventTouchUpOutside];
-(void) btnTocuhDown
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(kpTimerMethod:) userInfo:nil repeats:YES];
self.kpTimer = timer;
__weak typeof(self)weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void){
if (timer == self.kpTimer) {
[weakSelf.kpTimer fire];
}
});
-(void)kpTimerMethod:(NSTimer *)timer
if (self.btnDelete.highlighted)
{
[self deleteLastCharacter];
}
else
{
[timer invalidate];
self.kpTimer = nil;
}
-(void)deleteLastCharacter
NSString *strInput = self.textDocumentProxy.documentContextBeforeInput;
if (strInput.length > 1)
NSString *coupleOfLastCharacters = [strInput substringWithRange:NSMakeRange(strInput.length-2, 2)];
if( [#"yo" caseInsensitiveCompare:coupleOfLastCharacters] == NSOrderedSame ) {
[self.textDocumentProxy deleteLastCharacter];
}
}
[self.textDocumentProxy deleteLastCharacter];
-(void) btnTouchUp
[self.kpTimer invalidate];
self.kpTimer = nil;
- (void)addGesturesToKeyboard{
UILongPressGestureRecognizer *ges = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
ges.minimumPressDuration = 0.1;
ges.numberOfTouchesRequired = 1;
ges.delegate = self;
[self.mykeyboard.deleteKey addGestureRecognizer:ges];
}
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
[self.textDocumentProxy deleteBackward];
}
Set a counter as soon as the screen is touched, such as 2-5 seconds.
The situation known as Long press gesture, and here is the link to the simliar questions.
Long press gesture on UICollectionViewCell
I'm just starting out with my first Xcode project and I'm trying to create a square that moves back and forth on the screen using two timers, because I eventually want to make it so that the user can stop the object (which is a square) by tapping a button on the screen.
For now though, I've made the square move to the right side of the screen and move back, but unfortunately I cannot get it to stop at the other side of the screen.
My code right now is this:
- (void)viewDidLoad
{
Square.center = CGPointMake(-9, 246);
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare1)userInfo:nil repeats:YES];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)moveSquare1
{
Square.center = CGPointMake(Square.center.x + 0.3, Square.center.y);
if (Square.center.x > 290){
[SquareTimer1 invalidate];
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare2) userInfo:nil repeats:YES];
}
if (Square.center.x < -9){
[SquareTimer1 invalidate];
}
}
-(void) moveSquare2
{
Square.center = CGPointMake(Square.center.x - 0.3, Square.center.y);
}
The only part of my code that is not working is my second if statement. How can I fix this?
This should do it. Remove that second if from moveSquare1 and place it in moveSquare2
- (void)viewDidLoad
{
Square.center = CGPointMake(-9, 246);
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare1)userInfo:nil repeats:YES];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)moveSquare1
{
Square.center = CGPointMake(Square.center.x + 0.3, Square.center.y);
if (Square.center.x > 290){
[SquareTimer1 invalidate];
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare2) userInfo:nil repeats:YES];
}
}
-(void) moveSquare2
{
Square.center = CGPointMake(Square.center.x - 0.3, Square.center.y);
if (Square.center.x < -9){
[SquareTimer1 invalidate];
// If you want to move the Square back in the right side. Otherwise, comment this below line.
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare1) userInfo:nil repeats:YES];
}
}
Let me know if you have any doubts.
In my app, I want to use a NSTimer update my UIButton instance, but my button's title didn't change as the time elapse. My code is here:
-(void)fireTimer{
self.leftTime = 30;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerAction) userInfo:nil repeats:YES];
[self.timer fire];
}
- (void)timerAction
{
self.leftTime--;
NSLog(#"%d current runloop and mode is %#", self.leftTime, [NSRunLoop currentRunLoop].currentMode);
[self.customBtn setTitle:[NSString stringWithFormat:#"leftTime:%d", self.leftTime] forState:UIControlStateNormal];
if(self.leftTime == 0)
{
[self.customBtn setTitle:[NSString stringWithFormat:#leftTime :%d, self.leftTime] forState:UIControlStateNormal];
[self.timer invalidate];
}
}
And the NSLog output is correct, when self.timeLeft == 0, my button can change it's title correctly.
Can someone tell me what's the problem? thanks!
I find out the problem, I use KVO observe self.leftTimer, when the timer fire, I set my button.enable = NO, so it can't change the title, and when self.leftTime == 0, my button.enable = YES. My careless. Thanks all.
I have this app which has a timer in it and I want to be able to display a button at random points in that timer. Sort Of like a game setting where you have to get the button to get more time before it disappears. I already have some code , but the problem is that the timer that i already have is being messed up ( i can tell because it is linked to a label. It messed up because it goes down by 2 instead of 1 and this only happens when i have the code to make the button appear and disappear with the timer.
Here is the code to my timer that is being messed up:
-(IBAction)Ready:(id)sender {
[self performSelector:#selector(TimerDelay) withObject:nil afterDelay:1.0];
[self performSelector:#selector(randomTimer) withObject:nil afterDelay:0.5];
}
-(void)TimerDelay {
MainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
Here is the code to the button:
-(IBAction)Ready:(id)sender { //the same ready action as above
[self performSelector:#selector(TimerDelay) withObject:nil afterDelay:1.0];
[self performSelector:#selector(randomTimer) withObject:nil afterDelay:0.5];
}
-(void)TimerDelay {
MainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
- (void)randomTimer {
NSInteger randomTime = arc4random_uniform(0); //Some number between 0 and 9
timer = [NSTimer scheduledTimerWithTimeInterval:randomTime
target:self
selector:#selector(showButton)
userInfo:nil
repeats:NO];
}
- (void)showButton {
if(self.plus5.hidden == YES) {
self.plus5.hidden = NO;
}
else {
self.plus5.hidden = YES;
}
[self TimerDelay]; //Call random timer function again to run this method at a future random time
}
You are calling "randomTimer" and "TimerDelay" (this should be "timerDelay") one after the other and scheduling and REscheduling "timer".
I think you should reconsider your architecture, here...
EDIT: Use just one timer and let it manage your button.
- (void)somewhereInYourCode
{
shouldShowButton = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timeFired)
userInfo:nil
repeats:YES];
}
- (void)timeFired
{
// Here your countdown and...
if (shouldShowButton) {
NSInteger randomTimeInt = arc4random_uniform(9); // as suggested by Bergasms
float randomTimeFloat = randomTimeInt;
[self performSelector:#selector(showButton) withObject:nil afterDelay:randomTimeFloat];
shouldShowButton = NO;
}
}
This way your timer won't (probably) mess up.
This:
arc4random_uniform() will return a uniformly distributed random number
less than upper_bound.
is one of your problems.
NSInteger randomTime = arc4random_uniform(0); //Some number between 0 and 9
needs to be
NSInteger randomTime = arc4random_uniform(9); //Some number between 0 and 9
I cannot say for the rest of your code. But the line you have will always return 0, which means the random timer will always execute instantly.
So, Here is the problem. I am trying to make a timer for my game however it doesnt seem to run.
I started by making a property for nstimer:
#property (nonatomic) NSTimer gameTimer;
and synthesizing it:
#synthesize gameTimer = _gameTimer;
then I use this method to set it:
-(NSTimer *) gameTimer{
if (_gameTimer == nil) _gameTimer = [[NSTimer alloc]init];
return _gameTimer;
}
however when i try to start the timer through a uibutton:
- (IBAction)play:(UIButton *)sender {
_levelNumber = 1;
_en1v = -1;
_en2v = 1;
_en3v = -1;
[self setPath];
_gameTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:#selector(onTimer:) userInfo:nil repeats:YES];
self.play.hidden = TRUE;
}
it doesn't work.
I put an nslog into the onTimer: method and found out that the timer just isn't firing some how?
Am I making an obvious mistake?
You have not started the timer at all.
Use:
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(onTimer:) userInfo:nil repeats:YES];
And while stopping, (may be in stop: method)
[_gameTimer invalidate];
_gameTimer = nil;