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怎么使用,请君自行百度,很容易理解的.
时间: 2024-11-05 14:46:22