The initial use of Nstimer timer in IOS _ios

Source: Internet
Author: User

Create a timer (Nstimer)

-(void) viewdidload {
  [super viewdidload];
  [Nstimer scheduledtimerwithtimeinterval:1 target:self selector: @selector (actiontimer:) Userinfo:nil Repeats:yes];

-(void) Actiontimer: (Nstimer *) timer
{

}

Nstimer runs under default mode, which includes almost all input sources (except nsconnection) Nsdefaultrunloopmode modes.

The Actiontimer method is called once every 1s. Nstimer is not very easy to use. This is a relatively primary application of Nstimer.

Nstimer fails when the main interface is sliding

What does it mean to slide the main interface? This means that the main interface has UITableView or uiscrollview, sliding uitableview or Uiscrollview. This time the Nstimer failed.

Let's write a demo that starts the timer on a uiviewcontroller with UITableView, adds 1 per 1s digit, and displays the number on the Uilabel.

-(void) viewdidload {
  [super viewdidload];
  [Nstimer scheduledtimerwithtimeinterval:1 target:self selector: @selector (actiontimer:) Userinfo:nil Repeats:yes];

-(void) Actiontimer: (Nstimer *) timer
{
  self.number++;
  Self.label.text = [NSString stringwithformat:@ "%d", self.number];
  NSLog (@ "%d", self.number);
}

I omitted the creation of UITableView and Uilabel. Detailed code can click here to download: Iosstrongdemo,iosstrongdemo I will keep updating, everyone on the GitHub star.

This way when the user in the drag UITableView in Uitrackingrunloopmode, Nstimer is invalid, can not fire. The number on the Self.label cannot be updated.

Modify the Nstimer run loop

The workaround is to add it to the Uitrackingrunloopmode or Nsrunloopcommonmodes mode.

[[Nsrunloop Currentrunloop] Addtimer:timer Formode:uitrackingrunloopmode];

Or

[[Nsrunloop Currentrunloop] Addtimer:timer formode:nsrunloopcommonmodes];

Nsrunloopcommonmodes: is a collection of patterns that, when binding an event source to this pattern collection, is bound to each pattern within the collection.

Fire

We first use Nstimer to make a simple timer, every 5 seconds in the console output Fire. The more taken for granted is this:

@interface Detailviewcontroller ()
@property (nonatomic, weak) Nstimer *timer;
@end

@implementation Detailviewcontroller
-(ibaction) firebuttonpressed: (ID) Sender {
  _timer = [Nstimer scheduledtimerwithtimeinterval:3.0f
                       target:self
                      selector: @selector (timerfire:)
                      Userinfo:nil
                       Repeats:yes];
  [_timer fire];
}

-(void) Timerfire: (id) userinfo {
  NSLog (@ "Fire");
}
@end

After running, it is true that the console Fire every 3 seconds, but when we jump from this interface to other interfaces, we find that the console is still outputting Fire. It seems that the Timer did not stop.

Invalidate

Since there is no stopping, then we add the Invalidate method to the dealloc of Demoviewcontroller:

-(void) dealloc {
  [_timer invalidate];
  NSLog (@ "%@ dealloc", Nsstringfromclass ([self class]);
}

Run again, or not stop. The reason is that when the Timer is added to the runloop, it will be runloop strong reference:

Note in particular this run loops maintain strong references to their timers-so don ' t have to maintain your own G Reference to a timer on your have added it to a run loop.
Then the Timer will have a strong reference to Target (that is, self):

The Target is the "object" to send the "which" specified by aselector the timer fires. The timer maintains a strong reference to target until it (the timer) is invalidated.
That is, nstimer a strong reference to self, which causes self to not be released, and therefore does not go to Self's dealloc.

That being the case, then we can add a invalidate button:

-(Ibaction) invalidatebuttonpressed: (ID) Sender {
  [_timer invalidate];
}

Well, that's OK. (Someone on the SOF said it was time to execute _timer = nil after invalidate, fail to understand why, if you know why, you can tell me:)

This is also the case in the documentation for the Invalidate method:

You are must send this message from the "thread on which" the timer was installed. If you send this message from another thread, the input source associated and the timer may is removed from its run L OOP, which could prevent the thread from exiting properly.
The thread that the Nstimer is created on is going to stop, or it will cause the resource to be freed correctly. It looks like a lot of pits.

Dealloc

So the question is: if I just want this nstimer to go on and on until the Demoviewcontroller is destroyed, how can I stop it?

    • Nstimer is strongly referenced by Runloop, and if you want to release you will call invalidate method.
    • But I want to invoke the Invalidate method in the dealloc of Demoviewcontroller, but self is nstimer strong reference.
    • So I'm going to release Nstimer first, but I can't release it without calling the Invalidate method.
    • However, if you do not enter the Dealloc method, I cannot invoke the Invalidate method.
    • Well...


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.