zoukankan      html  css  js  c++  java
  • 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(@"
    [==ObjectDetector LIST==]
    %@", _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怎么使用,请君自行百度,很容易理解的.

  • 相关阅读:
    JS动态计算rem
    Vue数据双向绑定原理
    NOI2019 退役记
    友情链接
    算法博客总结
    总结各类错误(always online)
    学习笔记:powerful number求积性函数前缀和
    LOJ#2409. 「THUPC 2017」小 L 的计算题 / Sum(生成函数)
    多项式简单操作
    LOJ #3103. 「JSOI2019」节日庆典
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3864741.html
Copyright © 2011-2022 走看看