Reanimation
Reanimation

Reputation: 3336

Optimise a function that calls itself in Obj C

I've written a function that checks whether a live score has changed every 0.1 seconds, and if it has it plays a system sound on iPhone.

- (void) checkIfShouldHaptic {
    loadedScore = [self loadScoreFromKey:keyScore];            //load score saved in key
    controllerScore = [self checkCurrentScore];                //check current score

    if (loadedScore < controllerScore){                        //if score in key is less than controller score
        [self saveScore:controllerScore];                      //save new score in key
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);  //play system sound
        [self repeatCheckIfShouldHaptic];                      //repeat
    }
    else {                                                     //else score is not less
        [self repeatCheckIfShouldHaptic];                      //repeat
   }
}

- (void)repeatCheckIfShouldHaptic {
    [NSTimer scheduledTimerWithTimeInterval:timeDelayInSeconds target:self selector:@selector(checkIfShouldHaptic) userInfo:nil repeats:NO];
}

My programming capabilities are pretty limited so I was wondering if someone could show me if and how this could be optimised?

I'm not sure if a function calling itself over and over is good practice or if there's a better way to repeat a check. Thank you.

Upvotes: 0

Views: 56

Answers (2)

9to5ios
9to5ios

Reputation: 5545

I think you can use KVO

@property NSUInteger score;

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self addObserver:self forKeyPath:@"score" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"From KVO");

    if([keyPath isEqualToString:@"score"])
    {
        id oldScore = [change objectForKey:NSKeyValueChangeOldKey];
        id newScore = [change objectForKey:NSKeyValueChangeNewKey];

        NSLog(@"%@ %@", oldScore, newScore);
    }
}

Upvotes: 1

Serj Kultenko
Serj Kultenko

Reputation: 169

I would rewrite your code a little. IMHO Using NSTimer is more resources consuming operation then using GCD. Your approach is not so bad if you don't have any other options to receive some sort of notification.

- (void)checkIfShouldHaptic {
  loadedScore = [self loadScoreFromKey:keyScore];          //load score saved in key
  controllerScore = [self checkCurrentScore];              //check current score

  if (loadedScore < controllerScore){                      //if score in key is less than controller score
    [self saveScore:controllerScore];                      //save new score in key
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);  //play system sound
  }
  [self repeatCheckIfShouldHaptic];                      //repeat
}

- (void)repeatCheckIfShouldHaptic {
  __weak typeof(self) weakSelf = self;
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeDelayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [weakSelf checkIfShouldHaptic]
  });
}

Upvotes: 0

Related Questions