iOS-简单创建MLFinder并学习

1:创建工程的目录结构 1.1工程的目录结构
iOS-简单创建MLFinder并学习
文章图片
工程目录结构.jpg 1.2 工程思维导图
iOS-简单创建MLFinder并学习
文章图片
工程类图结构 2:原理解释 MLFinder的原理就是在viewcontroller返回时候(pop)检测当前的viewcontroller是否还有能力调用指定的willDealloc的方法。
【iOS-简单创建MLFinder并学习】总结成一句话:利用runtime发送消息的时候,receiver可以为nil,如[nil msg]。不会奔溃。
3:运行流程 iOS-简单创建MLFinder并学习
文章图片
运行流程图 4:源码如下 4.1 NSObject+MLFinder.m

#import "NSObject+MLFinder.h" #import #import const void *const kLatestSenderKey = &kLatestSenderKey; @implementation NSObject (MLFinder) + (void)swizzleSEL:(SEL)originalSEL withSEL:(SEL)swizzledSEL { Class class = [self class]; Method originalMethod = class_getInstanceMethod(class, originalSEL); Method swizzledMethod = class_getInstanceMethod(class, swizzledSEL); BOOL didAddMethod = class_addMethod(class, originalSEL, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAddMethod) { class_replaceMethod(class, swizzledSEL, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } - (BOOL)willDealloc {__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; } - (void)assertNotDealloc { NSLog(@"\n\n================assertNotDeallocassertNotDealloc================\n\n"); } @end

4.2 UINavigationController+MLFinder.m
#import "UINavigationController+MLFinder.h" #import "NSObject+MLFinder.h" #import static const void *const kPoppedDetailVCKey = &kPoppedDetailVCKey; @implementation UINavigationController (MLFinder) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self swizzleSEL:@selector(popViewControllerAnimated:) withSEL:@selector(swizzled_popViewControllerAnimated:)]; }); } - (UIViewController *)swizzled_popViewControllerAnimated:(BOOL)animated { UIViewController *poppedViewController = [self swizzled_popViewControllerAnimated:animated]; if (!poppedViewController) { return nil; }//// Detail VC in UISplitViewController is not dealloced until another detail VC is shown //if (self.splitViewController && //self.splitViewController.viewControllers.firstObject == self && //self.splitViewController == poppedViewController.splitViewController) { //objc_setAssociatedObject(self, kPoppedDetailVCKey, poppedViewController, OBJC_ASSOCIATION_RETAIN); //return poppedViewController; //}// VC is not dealloced until disappear when popped using a left-edge swipe gesture extern const void *const kHasBeenPoppedKey; objc_setAssociatedObject(poppedViewController, kHasBeenPoppedKey, @(YES), OBJC_ASSOCIATION_RETAIN); return poppedViewController; } @end

4.3 UIViewController+MLFinder.m
#import "UIViewController+MLFinder.h" #import "NSObject+MLFinder.h" #import const void *const kHasBeenPoppedKey = &kHasBeenPoppedKey; @implementation UIViewController (MLFinder) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self swizzleSEL:@selector(viewDidDisappear:) withSEL:@selector(swizzled_viewDidDisappear:)]; [self swizzleSEL:@selector(viewWillAppear:) withSEL:@selector(swizzled_viewWillAppear:)]; //[self swizzleSEL:@selector(dismissViewControllerAnimated:completion:) withSEL:@selector(swizzled_dismissViewControllerAnimated:completion:)]; }); } - (void)swizzled_viewDidDisappear:(BOOL)animated { [self swizzled_viewDidDisappear:animated]; BOOL hasBeenPop = [objc_getAssociatedObject(self, kHasBeenPoppedKey) boolValue]; if (hasBeenPop) { [self willDealloc]; } } - (void)swizzled_viewWillAppear:(BOOL)animated { [self swizzled_viewWillAppear:animated]; BOOL hasBeenPop = [objc_getAssociatedObject(self, kHasBeenPoppedKey) boolValue]; //NSLog(@"----%d",hasBeenPop); objc_setAssociatedObject(self, kHasBeenPoppedKey, @(NO), OBJC_ASSOCIATION_RETAIN); } @end

5:模拟代码
#import "TimerViewController.h" @interface TimerViewController () @property (nonatomic, strong) NSTimer * timer; @end @implementation TimerViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"timer"; //dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //[self timerClick]; //}); //self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(timerClick) userInfo:nil repeats:YES]; //[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; __weak typeof(self) ws = self; self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { [ws timerClick]; }]; [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } - (void)timerClick { NSLog(@"%s",__func__); } //- (void)viewWillDisappear:(BOOL)animated { //if (self.timer != nil) { //[_timer invalidate]; //_timer = nil; //} //} -(void)dealloc { NSLog(@"%s",__func__); [_timer invalidate]; _timer = nil; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSLog(@"---TimerViewController:viewWillAppear:%@",self); } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; NSLog(@"---TimerViewController:viewDidDisappear:%@",self); } @end

如果你觉得可以请添加我的公众号"洲洲哥"

    推荐阅读