ARC中用代码检测一个对象有没有释放掉
ARC中用代码检测一个对象有没有释放掉
你试过在ARC中用代码检测对象有没有释放掉这种事情呢?即使你想过肯定也不知道怎么去实现,因为,这里会用到一个你基本上没怎么接触过的类:NSHashTable.
我们以检测导航控制器push出一个新的控制器为例,以下是效果:
所有你需要的源码:
ObjectDetector.h + ObjectDetector.m
// // ObjectDetector.h // ARCBlock // // Copyright (c) 2014年 Y.X. All rights reserved. // #import <Foundation/Foundation.h> @interface ObjectDetector : NSObject + (void)startWatch; + (void)addToWatch:(id)object; + (NSArray *)allObjects; @end
// // ObjectDetector.m // ARCBlock // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "ObjectDetector.h" #ifndef GCDExecOnce #define GCDExecOnce(block) \ { \ static dispatch_once_t predicate = 0; \ dispatch_once(&predicate, block); \ } #endif static NSHashTable *_table = nil; static dispatch_source_t _dispatchSource = nil; static dispatch_queue_t _dispatchQueue = nil; @implementation ObjectDetector + (void)initialize { if (self == [ObjectDetector class]) { _table = [NSHashTable weakObjectsHashTable]; _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT); _dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _dispatchQueue); dispatch_source_set_timer(_dispatchSource, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC, 0); dispatch_source_set_event_handler(_dispatchSource, ^{ NSLog(@"\n[==ObjectDetector LIST==]\n%@", _table); }); } } + (void)startWatch { GCDExecOnce(^{ dispatch_resume(_dispatchSource); }); } + (void)addToWatch:(id)object { if (object == nil) { NSLog(@"object should not be nil."); return; } if ([_table containsObject:object] == NO) { [_table addObject:object]; } } + (NSArray *)allObjects { return [_table allObjects]; } @end
****-Prefix.pch
// // Prefix header // // The contents of this file are implicitly included at the beginning of every source file. // #import <Availability.h> #ifndef __IPHONE_3_0 #warning "This project uses features only available in iOS SDK 3.0 and later." #endif #ifdef __OBJC__ #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #import "ObjectDetector.h" #endif
AppDelegate.h
// // AppDelegate.m // NSHashTable // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. UINavigationController *NC = \ [[UINavigationController alloc] initWithRootViewController:[RootViewController new]]; self.window.rootViewController = NC; // 开始检测 [ObjectDetector startWatch]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } @end
RootViewController.m
// // RootViewController.m // NSHashTable // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "SecondViewController.h" @interface RootViewController () @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"任重而道远"; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 120, 30)]; button.center = self.view.center; button.layer.borderWidth = 1.f; button.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:20.f]; [button setTitle:@"YouXianMing" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; } - (void)buttonEvent:(UIButton *)button { [self.navigationController pushViewController:[SecondViewController new] animated:YES]; } @end
SecondViewController.m
// // SecondViewController.m // NSHashTable // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "SecondViewController.h" @interface SecondViewController () @end @implementation SecondViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.title = @"天道酬勤"; // 添加检测对象 [ObjectDetector addToWatch:self]; } @end
核心代码详解:
核心代码包括了用单例创建的GCD定时器以及维护一个弱引用集合
然后开启打印检测:
然后添加被检测对象:
大概就酱紫,是不是很容易呢-_-!,不过我当初想到这个点子可是花了挺长时间的,至于NSHashTable怎么使用,请君自行百度,很容易理解的.