web-dev-qa-db-fra.com

NSTimer timerWithTimeInterval: ne fonctionne pas

J'ai créé une application de test avec timer avant de l'implémenter dans mon projet. C'était la première fois que j'utilisais la minuterie. Mais le problème est quand j'ai implémenté le minuteur en utilisant [NSTimer timerWithTimeInterval: target: selector: userInfo: repeats: ]; , ça ne marche pas. Voici mon code, Interface:

@interface uialertViewController : UIViewController
{

    NSTimer *timer;
}

-(void)displayAlert;
-(void)hideandview;
@end

La mise en oeuvre:

@implementation uialertViewController
- (void)viewDidLoad {

    [self displayAlert];
    [super viewDidLoad];
}


-(void)displayAlert{

    timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(hideandview) userInfo:nil repeats:NO];

    alert = [[UIAlertView alloc] initWithTitle:@"testing" message:@"hi hi hi" delegate:nil cancelButtonTitle:@"continue" otherButtonTitles:nil];
    [alert show];




    [alert release];
    alert = nil;

}

-(void)hideandview{

    NSLog(@"triggered");

    [alert dismissWithClickedButtonIndex:0 animated:YES];

    [alert release];

    [self displayAlert];
}

@end

Puis j'ai changé[NSTimer timerWithTimeInterval: target: selector: userInfo: repeats: ];avec[NSTimer scheduledTimerWithTimeInterval: target: selector:userInfo: repeats: ];, ça marche. Quel était le problème avec timerWithTimeInterval:? Suis-je en train de manquer quelque chose dans ma première implémentation? Merci d'avance.

30
Midhun MP

scheduledTimerWithTimeInterval:invocation:repeats: et scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: créer des minuteries qui sont automatiquement ajoutées à un NSRunLoop, ce qui signifie que vous n'avez pas à les ajouter vous-même. Les avoir ajoutés à un NSRunLoop est ce qui les fait se déclencher.

Avec timerWithTimeInterval:invocation:repeats: et timerWithTimeInterval:target:selector:userInfo:repeats:, vous devez ajouter manuellement le minuteur à une boucle d'exécution, avec un code comme celui-ci:

[[NSRunLoop mainRunLoop] addTimer:repeatingTimer forMode:NSDefaultRunLoopMode];

D'autres réponses suggèrent que vous devez appeler fire vous-même. Vous ne le faites pas - il sera appelé dès que la minuterie aura été mise en boucle.

119
Joseph Humfrey

On peut également vouloir s'assurer d'ajouter un minuteur sur le fil principal.

assert(Thread.isMainThread)
let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(YourSelector), userInfo: nil, repeats: true)
2
Vladimir Shutyuk

Comme une réponse précédente a noté le calendrier sur le thread principal, mais plutôt que d'utiliser assert, placez-le sur le thread principal:

@objc func update() {
    ...
}

DispatchQueue.main.async {
            self.timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
        }

Et si l'async n'est pas souhaité, essayez ceci:

let schedule = {
            self.timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
        }

        if Thread.isMainThread {
            schedule()
        }
        else {
            DispatchQueue.main.sync {
                schedule()
            }
        }
1
Joe Pagliaro

La différence entre les deux est que la méthode timerWithTimeInterval renvoie un objet NSTimer qui n'a pas encore été déclenché. Pour déclencher la minuterie, vous devez utiliser [timer fire]; D'autre part, le scheduledTimerWithTimeInterval renvoie un NSTimer qui a déjà été déclenché.

Donc, dans votre première implémentation, il vous manquait juste [timer fire];

1
Chance Hudson