NSTimer / Countdown

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NSTimer / Countdown

    Hi leute,

    ich hoffe ihr könnt mir weiterhelfen :D

    Also ich habe eine TabBarApplication mit zwei TabBarItems einmal Main und Settings. In der Main habe ich einen Button der zu einer anderen View wechselt(switcht).
    In dieser View ist ein Countdown eingebaut der bei 30sek startet.

    Wechsel ich wieder zur Main und möchte wieder in die View mit dem Countdown dann läuft der Countdown einfach weiter ohne neu bei 30sek anzufangen.

    Hier ist der Code dazu

    .h

    Quellcode

    1. IBOutlet UILabel *countLabel;
    2. NSTimer *timer;
    3. NSUInteger time;
    4. - (void)updateLabel;
    5. - (void)countDown;
    6. @property (nonatomic, retain) UILabel *countLabel;
    7. @property (nonatomic, retain) NSTimer *timer;


    .m

    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. time = 30.0;
    4. timer = [NSTimer scheduledTimerWithTimeInterval:(1.0) target:self selector:@selector(countDown) userInfo:nil repeats:YES];
    5. }
    6. - (void)countDown {
    7. time = time -1;
    8. if (time == 0) {
    9. [timer invalidate];
    10. }
    11. [self updateLabel];
    12. }
    13. - (void)updateLabel {
    14. countLabel.text = [NSString stringWithFormat:@"%i", time];
    15. }
    Alles anzeigen


    Da ich auch ein Bild habe was beim ersten aufrufen angezeigt wird und beim zweiten mal nicht, denke ich das ich den viewController neu laden muss. Oder sehe ich das falsch?

    das switchen der view habe ich laut dieser anleitung gemacht und mit dem source code Two XIBs MVC-compliant code.

    Multiple XIB how-to

    Ich danke euch!
  • RE: NSTimer / Countdown

    Starte den Timer nicht im viewDidLoad sonder im viewDidAppear:, dann wird er immer gestartet, wenn der View angezeigt wird.

    Du solltest dann noch im viewDidDisappear: oder viewWillDisappear: einen evtl. laufenden Timer beenden, damit dieser nicht weiter läuft, wenn der View nicht mehr angezeigt wird.
  • Ich würde es so machen:

    AppController.h

    Quellcode

    1. @interface AppController : NSObject {
    2. IBOutlet UILabel *label;
    3. NSTimer *timer;
    4. NSDate *date;
    5. }
    6. @property(readwrite, retain) NSTimer *timer;
    7. @property(readwrite, retain) NSDate *date;
    8. -(IBAction)startCountdown:(id)sender;


    AppController.m

    Quellcode

    1. @implemetation AppController
    2. -(id)init {
    3. self = [super init];
    4. timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countDown:) userInfo:nil repeats:YES];
    5. return self;
    6. }
    7. -(IBAction)startCountdown:(id)sender {
    8. self.date = [[NSDate alloc] initWithTimeIntervalSinceNow:30.0];
    9. [timer fire];
    10. }
    11. -countDown:(NSTimer *)aTimer {
    12. label.text = [NSString stringWithFormat:@"%i", [self.date timeIntervalSinceNow]];
    13. if([self.date timeIntervalSinceNow] <= 0) {
    14. [timer invalidate];
    15. }
    16. }
    Alles anzeigen


    Nicht getestet, müsste aber funktionieren.
    Per if-Abfrage kannst du dann immer das Interface verändern, wenn es sein muss...
    Skeiron
    Der Mac heiligt die Mittel.
  • danke für eure antworten

    habe jetzt mit viewDidDisappear probleme und zwar stürzt mein programm ab wenn ich di view verlassen möchte. gehe eigentlich davon aus das der code richtig ist. Wo ist das problem ?(

    Quellcode

    1. - (void) viewDidDisappear:(BOOL)animated {
    2. [timer invalidate];
    3. timer = nil;
    4. }
  • Original von blackyE
    habe jetzt mit viewDidDisappear probleme und zwar stürzt mein programm ab wenn ich di view verlassen möchte. gehe eigentlich davon aus das der code richtig ist. Wo ist das problem ?(


    Definiere mal ein retain Property für timer und verwende dann überall self.timer.

    Weiterhin solltest Du in der Methode countDown, die Referenz auf den Timer mit self.timer = nil löschen, wenn der Countdown abgelaufen ist.
  • nun funktioniert es. Danke euch!!! =)

    jetzt habe ich noch folgendendes problemchen.

    ich habe diesen code

    Quellcode

    1. - (void)showImage {
    2. UIImage *hintergrund = [UIImage imageWithData: [[NSUserDefaults standardUserDefaults] objectForKey: @"UserDefinedImage"]];
    3. if (!hintergrund) hintergrund = [UIImage imageNamed: @"scaryface.png"];
    4. faceView.image = hintergrund;
    5. [UIView beginAnimations:nil context:faceView];
    6. [UIView setAnimationDelay:0.5];
    7. [UIView setAnimationDuration:0.25];
    8. [faceView setAlpha:0.0];
    9. [UIView commitAnimations];
    10. CFBundleRef mainBundle;
    11. mainBundle = CFBundleGetMainBundle ();
    12. soundFileURLRef = CFBundleCopyResourceURL (mainBundle,CFSTR ("schrei"),CFSTR ("aif"), FALSE);
    13. AudioServicesCreateSystemSoundID (soundFileURLRef,&soundFileObject);
    14. AudioServicesPlaySystemSound (self.soundFileObject);
    15. AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
    16. [[NSUserDefaults standardUserDefaults] removeObjectForKey: @"UserDefinedImage"];
    17. [[NSUserDefaults standardUserDefaults] synchronize]; // Sofort löschen + Speicher freimachen
    18. }
    19. - (void)viewWillAppear:(BOOL)animated {
    20. if ([[NSUserDefaults standardUserDefaults] boolForKey:@"ShowScaryFace"])
    21. [self performSelector:@selector(showImage) withObject:nil afterDelay:5.0];
    22. [super viewWillAppear:animated];
    23. }
    Alles anzeigen


    jetzt ist es so wie bei dem timer. Das Bild wird nach 5sek angezeigt. wenn ich aber wieder die view neu lade wird nur der sound abgespielt aber das bild nicht. Muss ich das wieder mit der viewDidDisappear methode machen?
  • Du willst vermutlich mit dem Setzen von nil bewirken, dass damit auch ein release der Variablen erfolgt. In dem Fall vermischst Du allerdings Objective-C und Objective-C 2.0. Im Normalfall hast Du den Timer als Property definiert und willst den Setter benutzen, um den aktuellen Wert zu setzen. Je nach Art deines Setters (retain z.B.) könntest Du mit der Punktnotation in Objective-C 2.0 den Setter auch zum Releasen verwenden, wenn Du das so schreibst:

    Quellcode

    1. self.timer = nil;
    Damit wird das Setzen von nil im synthetisierten Setter abgefangen und auch ein Release an den Timer geschickt. Wenn Du der Variablen ohne die Angabe von self und dem Punkt verwendest, wird ihr direkt nil zugewiesen und ein eventuell vorhandener Setter nicht verwendet. (Scheinbar ist es ja im Moment modern, einfach nur noch auf Bände von Amin zu verweisen. In diesem Fall ist es dann Band 1 und dort die Speicherverwaltung).

    Solltest Du klassisch nach Objective-C (1.0 oder wie man das auch immer nennt) vorgehen, dann schickst Du ein

    Quellcode

    1. [timer release];
    und evtl. der Klarheit wegen noch ein

    Quellcode

    1. [self setTimer:nil];
    wenn Du einen Setter implementiert hast - was so sein sollte. Die Frage ist dann, wie es im Setter aussieht und ob der evtl. schon wie ein von Objective-C 2.0 synthetisierter funktioniert. Wenn Du keinen Setter gebaut hast, kannst Du (wohlgemerkt) nach dem release auch

    Quellcode

    1. timer = nil;
    setzen. Ob Du nun einen Setter hast oder nicht - das Setzen von nil dient dann der Klarheit beim Lesen des Programmtextes und setzt dir den Zeiger auf einen definierten Wert, auf den man sich bei späteren Abfragen verlassen kann.

    Gruß,

    Frank

    P.S.: Cocoa Dev Central: Learn Objective-C
  • Original von scaramangado
    Ich hatte auch schon hässliche crashs, wenn ein laufender Timer released wurde. Am besten immer per -isValid prüfen.

    Das kann aber nicht an der Timer-Instanz liegen. Es ist zulässig, eine Instanz für einen One-Shot-Timer zu releasen, obwohl der Timer noch läuft. Das ist ein reiner Wrapper.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von blackyE
    jetzt ist es so wie bei dem timer. Das Bild wird nach 5sek angezeigt. wenn ich aber wieder die view neu lade wird nur der sound abgespielt aber das bild nicht. Muss ich das wieder mit der viewDidDisappear methode machen?

    Wie lädst Du denn den View und zeigst Du diesen an?
  • hier habe ich mal ein den code für das switchen der view!

    Quellcode

    1. - (void)applicationDidFinishLaunching:(UIApplication *)application {
    2. // Override point for customization after app launch
    3. helloWorldColor = [UIColor darkGrayColor]; //initialize our color variable to dark gray
    4. //set up firstViewController ivar
    5. FirstViewController *aFirstView = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:[NSBundle mainBundle]];
    6. [self setFirstViewController:aFirstView];
    7. [aFirstView release];
    8. //add firstViewController's view to the window
    9. [window addSubview:[firstViewController view]];
    10. //set onFront equal to YES since firstViewController's view is showing
    11. onFront = YES;
    12. [window makeKeyAndVisible];
    13. //tell the notification center to notify the app delegate if a @"DelegateFlipViewNotification" is received
    14. //Nothing will happen as a result of this unless you uncomment the indicated lines in SecondViewController.m
    15. NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
    16. [dc addObserver:self selector:@selector(flipViews:) name:@"DelegateFlipViewNotification" object:nil];
    17. }
    18. - (void)flipViews:(id)sender {
    19. //animation block to flip the views in and out of the screen
    20. [UIView beginAnimations:nil context:NULL];
    21. [UIView setAnimationDuration:1.5];
    22. if(onFront) {
    23. if(!secondViewController) {
    24. SecondViewController *aSecondView = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:[NSBundle mainBundle]];
    25. [self setSecondViewController:aSecondView];
    26. [aSecondView release];
    27. }
    28. [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:window cache:YES];
    29. [[firstViewController view] removeFromSuperview];
    30. [window addSubview:[secondViewController view]];
    31. onFront = NO;
    32. } else {
    33. [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:window cache:YES];
    34. [[secondViewController view] removeFromSuperview];
    35. [window addSubview:[firstViewController view]];
    36. onFront = YES;
    37. }
    38. [UIView commitAnimations];
    39. }
    40. - (void)dealloc {
    41. [helloWorldColor release];
    42. [firstViewController release];
    43. [secondViewController release];
    44. [window release];
    45. [super dealloc];
    46. }
    Alles anzeigen