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怎么使用,请君自行百度,很容易理解的.

时间: 2024-11-05 14:46:22

ARC中用代码检测一个对象有没有释放掉的相关文章

Python检测一个对象是否为字符串类的方法

  这篇文章主要介绍了Python检测一个对象是否为字符串类的方法,即检测是一个对象是否是字符串对象,本文还讲解了一个有趣的判断方法,需要的朋友可以参考下 目的 测试一个对象是否是字符串 方法 Python的字符串的基类是basestring,包括了str和unicode类型.一般可以采用以下方法: 代码如下: def isAString(anobj): return isinstance(anobj,basestring) 不过以上方法对于UserString类的实例,无能无力. 代码如下:

BitDefender一个恶意代码检测和清除按需扫描工具

BitDefender Linux版是一个以命令行或脚本,以及手动指定的方式对单个文件或者整个文件系统进行恶意代码检测和清除的按需扫描工具. 它是一个http://www.aliyun.com/zixun/aggregation/29607.html">自由软件,不需要任何使用许可文件你就能自由使用和传播. 下载 下载debian文件: * wget http://download.bitdefender.com/unices/old/linux/free/bitdefender-cons

使用RTC构建引擎搭建静态代码检测BEAM的自动测试环境

通过自定义构建引擎和构建定义可以很方便的将各种代码测试或者编译工具集成入 RTC 自动化运行,同时也可以很便利的将测试或者编译结果上传回 RTC,供开发和测试人员查看. IBM Checking Tool for Bugs Errors and Mistakes(本文后面将采用其文字缩写 BEAM)是 IBM 开发的一个静态分析工具,用于查找 C.C + +和 Java 程序中的错误.它直接对代码进行分析,不会尝试执行源代码,也不需要对代码进行编译连接,因此并不需要为代码编写任何测试用例.它是对

【Java编码规范】《阿里巴巴Java开发手册》终极版更新,在线代码检测及IDE插件发布

        -------------- 2017.10.14更新 -------------- <阿里巴巴Java开发手册(终极版)>正式发布,这是史上内容最全.修正最为彻底的一个版本,并且增加了单元测试规约内容,这也是阿里官方对外发布的最后一个PDF版本,值得收藏.   <阿里巴巴Java开发手册>是阿里内部Java工程师所遵循的开发规范,涵盖编程规约.单元测试规约.异常日志规约.MySQL规约.工程规约.安全规约等,这是近万名阿里Java技术精英的经验总结,并经历了多次大

ios-如何判断一个对象是否被释放?

问题描述 如何判断一个对象是否被释放? 如题 当kkcell 移出屏幕可见范围后,由于UITableView自动释放了cell结果音频播放结束后也要调用audioPlayerDidFinishPlaying方法. kkcell已经不存在了导致crash. 用if(kkcell) if(kkcell!=nil) 都无效,大家遇到过这样的问题吗? UITableViewCell *kkcell; (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)p

windows-SVN的pre-commit中做代码检测,成功后提交

问题描述 SVN的pre-commit中做代码检测,成功后提交 事情是这样的: 我想实现,在提交代码时,对提交的代码进行编码规范检测,检测通过才能提交成功. 即需要在pre-commit实现检测:检测后面的已经做好. 当前问题是,怎么实现在pre-commit中检测到我的提交代码,并同步更新到我的测试服务器上? 在pre-commit 中只有两个传入参数,路径和事件名,还有一个svnlook命令可以用,感觉自己比较春蠢,不知道怎么做, 求大神拯救,急 急 急 送上全部家当,呜呜,解答. 总结下,

应用-vb中用代码如何将com+组件卸载?

问题描述 vb中用代码如何将com+组件卸载? '函数名称:DeleteComponent'作用:删除对应com+应用中的组件'参数:sFolder COM+目录,sFileName组件名Public Function DeleteComponent(sComFolder As String, sFileName As String) As Boolean Dim oo As Object Dim oKey As Variant Dim oComponents As Object Dim i A

C#中用代码控制命令来备份mysql的数据,可是备份不了,怎么回事??

问题描述 C#中用代码控制命令来备份mysql的数据,可是备份不了,怎么回事?? 方法1:Process.Start(""cmd.exe""/c mysqldump -hlocalhost -P3306 -uroot –p12111 samp_db1 > E:cs.sql"");方法2:ProcessStartInfo psi = new ProcessStartInfo();psi.FileName = ""cmd.e

2.2、Android Studio通过注解提升代码检测

使用像Lint这样的代码检测工具可以帮助你发现问题和提升代码,但是代码检测在有些地方很难应用.例如,Android的资源ID,使用一个int类型来表示字符.图像.颜色或者其他资源类型所以代码检测工具不能分辨这是一个字符串资源,还是一个颜色资源.这种情况下,即使你使用代码检测工具,你的app可能会渲染失败或者不能运行. 注解允许你为Lint这样的代码检测工具提供提示来帮助Lint检测更深层次问题.当你使用代码检测工具的时候,注解可以帮助你检测问题,比如空指针异常和资源类型冲突. Android支持