views:

37

answers:

2

so here is the problem i have, i created two NSTimer objects and they are fired when i button is pressed. then the user has 20 seconds to press another button which forces an alert to popup where they enter a validation code, and when they press the confirm button on the alert it is supposed to stop the timer. what is happening is that everything works until they press confirm but instead of the timer stopping it hangs for a second( which im thinking is a delay caused by the keyboard dismiss animation) and then the timer continues. any help would be greatly appreciated and here is all relevant code:

#import "hackergameViewController.h"
#import <AudioToolbox/AudioToolbox.h>


@implementation hackergameViewController

@synthesize decryptLabel, crackLabel, decryptButton, crackButton, submit, numberToDecrypt, numberToCrack, stopDecryptButton, stopCrackButton, inputCode;
@synthesize soundFileURLRefBeep;
@synthesize soundFileURLRefBuzz;
@synthesize soundFileObjectBeep;
@synthesize soundFileObjectBuzz;


NSTimer *decryptTimer;
NSTimer *crackTimer;
int crackTime;
int decryptTime;
NSString *codeToConfirm;

#pragma mark UIAlertView
- (void)confirm:(UIAlertView *)confirm clickedButtonAtIndex:(NSInteger)buttonIndex {
    if(buttonIndex == 0){
        [confirm dismissWithClickedButtonIndex:0 animated:YES];
    }
    else {
            if (inputCode.text == codeToConfirm) {
            [self stopCrack];
            [self stopDecrypt];
        }
    }
}

-(void) generateDecryptionCode{
    codeToConfirm = [NSString stringWithFormat:@"%i%i%i%i%i%i", arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10];
    numberToDecrypt.text = codeToConfirm;
}

-(void) generateCrackCode{
    codeToConfirm = [NSString stringWithFormat:@"%i%i%i%i%i%i%i%i%i%i", arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10,arc4random() % 10];
    numberToCrack.text = codeToConfirm;
}

- (void)dealloc {
    [decryptLabel release];
    [decryptButton release];
    [crackLabel release];
    [crackButton release];
    [submit release];
    [numberToCrack release];
    [numberToDecrypt release];
    [super dealloc];
}

- (void) confirmCode{
    UIAlertView *confirm = [[UIAlertView alloc] initWithTitle:@"Confirm Code" message:@"Please Input The Correct Code:"  delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Confirm Code", nil];
    inputCode = [[UITextField alloc] initWithFrame:CGRectMake(12, 45, 260, 25)];
    CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0, 60);
    [confirm setTransform:myTransform];
    [inputCode setBackgroundColor:[UIColor whiteColor]];
    [confirm addSubview:inputCode];
    [confirm show];
    [confirm release];
    [inputCode release];

}


- (void) decryptTimerFires{

    if(decryptTime > 0){
        decryptTime--;
        decryptLabel.text = [NSString stringWithFormat:@"%g",    (float)decryptTime/10];
        if(decryptTime%10 == 0){
            AudioServicesPlaySystemSound (self.soundFileObjectBeep);
        }

    }
    else{
        [decryptTimer release];
        decryptTimer = nil;
    }
}
- (void) crackTimerFires{

    if(crackTime > 0){

        crackTime--;
        crackLabel.text = [NSString stringWithFormat:@"%g", (float)crackTime/10];
        if(crackTime%10 == 0){
            AudioServicesPlaySystemSound (self.soundFileObjectBeep);
        }
        else if(crackTime == 0){
            AudioServicesPlaySystemSound (self.soundFileObjectBuzz);
        }
    }
    else{
        [crackTimer release];
        crackTimer = nil;
    }
}

-(void) stopDecrypt{
    [decryptTimer invalidate];
    [decryptTimer release];
    decryptTimer = nil;
}
-(void) stopCrack{
    [crackTimer invalidate];
    [crackTimer release];
    crackTimer = nil;
}

-(IBAction)decrypt{
    [self generateDecryptionCode];
    decryptTime = 200;
    decryptTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(decryptTimerFires) userInfo:nil repeats:YES];
    [decryptTimer fire];

}

-(IBAction)crack{
    [self generateCrackCode];
    crackTime = 200;
    crackTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(crackTimerFires) userInfo:nil repeats:YES];
    [crackTimer fire];

}
A: 

First, you should not be calling "fire" manually unless you want the timer to fire immediately.

Second, you should call -invalidate rather than -release (as you're doing in your -decryptTimerFires and -crackTimerFires methods) when you want your timer to go away, then nil it out as you're doing. You're using the +scheduled... class method, which schedules the timer on the current run loop (which retains it, so it's not up to you to release it). -invalidate removes it from the run loop properly.

From the docs:

This method is the only way to remove a timer from an NSRunLoop object.

Joshua Nozzi
A: 

In your confirm method, are you sure that your inputCode.text == codeToConfirm is returning true? Have you tried using [inputCode.text compare:codeToConfirm]? From what I can see, your timers only get invalidated in stopCrack and stopDecrypt, which only get called if that comparison succeeds.

highlycaffeinated
i tried your suggestion but it is still working the same, i just realized it must be something about the comparison because i have `stopDecrypt` and `stopCrack` connected to buttons and the buttons work properly. does inputCode.text return a value that can be compared with an NSString or do i have to type cast it or something?
Joe
@Joe inputCode.text returns an NSString, so the values should be comparable. Since one of the strings is input by the user, `localizedCompare:` might serve you better.
highlycaffeinated