The key code in MLeaksFinder is: PS: Refer to the FBRetainCycleDetector + MLeaksFinder

- (BOOL)willDealloc {
     NSString *className = NSStringFromClass([self class]);
     if ([[NSObject classNamesWhitelist] containsObject:className]) return NO; 
     NSNumber *senderPtr = objc_getAssociatedObject([UIApplication sharedApplication], kLatestSenderKey);
     if ([senderPtr isEqualToNumber:@((uintptr_t)self)]) return NO; 
      __weak id weakSelf = self;
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        __strong id strongSelf = weakSelf;
       [strongSelf assertNotDealloc];
     });
     return YES;
}
Copy the code

The most important passage is:

 __weak id weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
   __strong id strongSelf = weakSelf;
   [strongSelf assertNotDealloc]; 
});
Copy the code

So this is kind of clever, this is kind of clever, this is kind of lazy code, so after 2 seconds of normal page exit, if there’s no memory leak, the VC of the page will be released, the View will be released, and the strongSelf reference will be nil, OC messages to nil ([strongSelf assertNotDealloc]) do not respond. If the response statement has not been released, it becomes a suspect object. Need to be “grilled”.

Let’s make a split line here, and I notice that for 2 seconds, if weakSelf is not nil, strongSelf will always be there, and I suddenly have some ideas about __weak and __strong,

What we usually think about a lot is, normally, no delay, no singleton, etc.

Requirement: When we add delay, print to view objects decorated with __strong

1. Create an empty project and add a navigation bar to main.stroyBoard. Click on the blank screen to push a controller object VC 3. Click on the blank screen to pop remove 4. Add delay operation to pop removal code in controller object VC

#import "ViewController.h" #import "TEViewController.h" @interface ViewController () @end @implementation ViewController  - (void)viewDidLoad { [super viewDidLoad]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSLog(@"111"); TEViewController *vc = [[TEViewController alloc]init]; [self.navigationController pushViewController:vc animated:YES]; } @endCopy the code

#import "TEViewController.h" @interface TEViewController () @property(nonatomic, assign) CGFloat isDelay; @end @implementation TEViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor redColor]; } - (void)dealloc { NSLog(@"delloc "); } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { __weak typeof(self) weakSelf = self; NSLog(@"1 : %@",weakSelf); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"Delay 2s"); __strong typeof(self) strongSelf = weakSelf; StrongSelf. IsDelay = 1.0; StrongSelf. IsDelay = 2.0; StrongSelf. IsDelay = 3.0; StrongSelf. IsDelay = 4.0; NSLog(@"2 : %@-%@",strongSelf,weakSelf); NSLog(@"strongSelf.isDelay : %f",strongSelf.isDelay); }); NSLog(@"3 : %@",weakSelf); [self.navigationController popViewControllerAnimated:YES]; //pop remove} @endCopy the code

When executing the code in the dispatch_after task, weakSelf is nil, so executing to __strong typeof(self) strongSelf = weakSelf;

So weakSelf is nil.

Print the result when you click return

2020-07-06 15:06:03.795880+0800 123qwe[10312:190955] 1220-07-06 15:06:04.497275+0800 123qwe[10312:190955] 1: <TEViewController: 0x7f8fe4c13be0> 2020-07-06 15:06:04.497502+0800 123qwe[10312:190955] 3: <TEViewController: 0x7F8fe4c13be0 > 2020-07-06 15:06:04.497502+0800 123qwe[10312:190955] 0x7F8FE4C13BE0 > 2020-07-06 15:06:05.004544+0800 123qWe [10312:190955] DELloc 2020-07-06 15:06:06.497705+0800 123qwe[10312:190955] Delay 2s 2020-07-06 15:06:06.497946+0800 123qwe[10312:190955] 2: (NULL)-(NULL) 2020-07-06 15:06:06.498125+0800 123qWe [10312:190955] StrongSelf. isDelay: 0.000000Copy the code

Conclusion:

  1. An object that has not been freed after 2 seconds will also have a false alarm of a memory leak if a child thread asynchronously delays operations.
  2. Singletons that have not been freed will also have them. Singletons should be whitelisted.
  3. Modifiers for __weak and __strong. The scenarios used also need to be considered, noting whether the __weak modified object has been destroyed by the time __strong is executed.

Author: li_ ceremony light links: www.jianshu.com/p/921fb48b1… The copyright of the book belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.