简体   繁体   中英

Better alternative for NSTimer

I'm just wondering, is there a better, more efficient function to use than NSTimer? I have a NSTimer code like this on my ViewDidLoad function:

[NSTimer scheduledTimerWithTimeInterval:900.0f target:self selector:@selector(methodToRun) userInfo:nil repeats:YES];

With the function methodToRun:

-(void)methodToRun {
     if(currentTime == presetTime) {
        //do something
     }
}

This works fine but the problem is, this eats up a lot of memory and I am getting memory warnings. So, what's a better, more efficient and less memory consuming way of triggering my methodToRun continuously to check if the currentTime is equal to presetTime?

You can use dispatch_after .

An alternative solution to this can be achieved by using the dispatch_after method and a weak pointer to self.

__weak id weakSelf = self;
__block void (^timer)(void) = ^{

    double delayInSeconds = 1.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        id strongSelf = weakSelf;

        if (!strongSelf) {
            return;
        }

        // Schedule the timer again
        timer();

        // Always use strongSelf when calling a method or accessing an iVar
        [strongSelf doSomething];
        strongSelf->anIVar = 0;
    });
};

// Start the timer for the first time
timer(); 

With this you will have a scheduled task that will be called at every sec, it will not retain the target (self) and it will end itself if the target is deallocated.

Source: NSTimer alternative

Based on @Anoop's answer here is swift version:

func timerGCD() -> ()
{
    weak var weakSelf = self

    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(1.0 * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue())
        {
            if let strongSelf = weakSelf
            {
                // Always use strongSelf when calling a method or accessing an iVar
                strongSelf.doSomething()

                // Schedule the timer again
                strongSelf.timerGCD()
            }
    }
}

And then simply start it with:

    timerGCD()

Better swift version using optional chaining and weak self

    func timerGCD() -> ()
    {
        dispatch_after(
            dispatch_time(
                DISPATCH_TIME_NOW,
                Int64(1.0 * Double(NSEC_PER_SEC))
            ),
            dispatch_get_main_queue())
            { [weak self] in
                    self?.doSomething()
                    // Schedule the timer again
                    self?.timerGCD()
            }
    }

Just run a while loop, and use sleep() or usleep() functions at the end of the loop which will define the time interval.
PS: don't do it on main thread
Edit: I see that I am getting downvotes, but can somebody tell me what is wrong with this approach?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM