iOS - Solution to NSTimer circular reference

iOS - Solution to NSTimer circular reference

Occurrence scenario

In Controller B there is a NSTimer

  1. @property (strong, nonatomic) NSTimer *timer;

You create it and attach it to the main runloop

  1. self.timer = [NSTimer scheduledTimerWithTimeInterval:1
  2. target:self selector:@selector(timerAction:) userInfo:nil repeats: true ];

Then when exiting Controller B, I forgot to turn off the timer.

Controller B will not be released, and B and timer will have a circular reference because self is written directly into the timer when it is created.

Method 1

Since we can't pass self directly, let's try passing weakSelf

  1. __weak typeof(self) weakSelf = self;
  2.   
  3. self.timer = [NSTimer scheduledTimerWithTimeInterval:1
  4. target:weakSelf selector:@selector(timerAction:) userInfo:nil repeats: true ];

The test result shows that a circular reference still occurs. B is not released, and timer has a strong reference to the weakSelf variable. Timer -> weakSelf -> B -> timer forms a circular reference among the three.

Method 2

Set up a wrapper class, wrap Controller B and put it in the timer, like this

I think Controller B is several MB in size, and leaking it is a waste of memory.

WeakWrap is only a few hundred bytes, so it doesn't matter if it leaks.

WeakWrap has a weak reference to Controller B. WeakWrap wraps Controller B and passes it into the timer. Even if you forget to turn off the timer, only WeakWrap and timer will be leaked.

Theoretically, there are still memory leaks, but they are relatively rare. If a Controller is frequently entered and exited, one timer is lost every time it enters and exits. If there are dozens of leaked timers hanging on the main run loop, it will affect performance and smoothness. If you want dozens of timers to fire at the same time and call the timer event response method, the overhead is still quite large.

Method 3

NSTimer is known to strongly reference the parameter target:self. If you forget to close the timer, anything you pass in will be strongly referenced. Just implement a timer. The function of a timer is to call a method at a fixed time. The calling time of NSTimer is not accurate! It is hung on the runloop and is affected by thread switching and the execution time of the previous event.

Use dispatch_asyn() to execute functions at a fixed time. See the following code.

  1. - (void)loop {
  2. [self doSomething];
  3. ......
  4. // Rest for time seconds, then adjust loop to implement timed call
  5. [NSThread sleepForTimeInterval: time ];
  6. dispatch_async(self.runQueue, ^{
  7. [weakSelf loop];
  8. });
  9. }

Dispatch_async loop does not generate recursive calls

dispatch_async adds a task to the queue, and GCD calls back [weakSelf loop]

This method solves the problem that the timer cannot be released and cannot be removed from the runloop.

Using this method, I wrote a timer that does not have a circular reference. When the controller is released, the timer will also stop releasing automatically. You can even write self directly in the timer block without a circular reference. GitHub download address

Method 4

I have never encountered the problem of circular references in NSTimer before, because I have always used them in pairs, opening them in viewWillAppear and closing them in viewWillDisappear. If they are not closed, so many timers mounted on the runloop will affect the performance and fluency. Just like managing memory, if the application and release are used in pairs, there will be no leakage. The principle of whoever applies should release. However, if the team is large, others may make mistakes and cause leakage, which can be solved from the technical point of view and the team programming standards.

For example, some specifications are set, such as the controller must be successfully destroyed when exiting, and memory cannot be leaked. Self cannot be written in Block, etc.

<<:  When knowledge graphs “meet” deep learning

>>:  Android resolution adaptation test

Recommend

B station brand joint marketing strategy!

In a world where everything can be co-branded, co...

This fleshy worm knows the "gun fighting technique" in the "God Drama"

Recently, the sand dollar has become a hot topic ...

GALAXY A3009——Stylish and smart pocket phone

Samsung GALAXY A3009 is a high-performance mobile...

Detailed explanation of the order design model in the e-commerce platform!

As a business subsystem, the order system is very...

Want your baby to grow taller? Huaxi experts suggest: Do these 3 things!

Baby's height This has always been a concern ...

Analysis of the "Fan Deng Reading" activity

The case analysis brought to you today is Fan Den...

How to quote for SEO website ranking optimization plan?

For SEO website optimization personnel (newbies),...

Low-cost brand communication rules!

The “Brand Golden Triangle Rule” for building a b...