设计一个不强引用对象的单例字典

设计一个不强引用对象的单例字典

大家都知道,使用NSDictionary存储对象的时候会强引用对象,导致被存储对象的引用计数+1,有时候,我们想用单例来存储对象,但又不希望强引用存储的对象,这该怎么实现呢?

在这里,我们可以使用NSMapTable来实现这个功能.

我直接给出源码:

WeakDictionary.h   +   WeakDictionary.m

//
//  WeakDictionary.h
//  弱引用字典
//
//  http://www.cnblogs.com/YouXianMing/
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <Foundation/Foundation.h>

#define GET_WEAK_OBJECT(key)                 [WeakDictionary objectForKey:(key)]
#define REGISTER_WEAK_OBJECT(object, key)    [WeakDictionary addObject:(object) forKey:(key)]

@interface WeakDictionary : NSObject

+ (void)addObject:(id)object forKey:(NSString *)key;
+ (id)objectForKey:(NSString *)key;

@end
//
//  WeakDictionary.m
//  弱引用字典
//
//  http://www.cnblogs.com/YouXianMing/
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "WeakDictionary.h"

static NSMapTable  *weakDictionary = nil;

@implementation WeakDictionary

+ (void)initialize
{
    if (self == [WeakDictionary class])
    {
        // 强引用key值弱引用object
        weakDictionary = [NSMapTable strongToWeakObjectsMapTable];
    }
}

+ (void)addObject:(id)object forKey:(NSString *)key
{
    if (object == nil || key == nil)
    {
        NSLog(@"object & key should not be nil.");
        return;
    }
    
    if ([weakDictionary objectForKey:key] == nil)
    {
        [weakDictionary setObject:object forKey:key];
    }
}

+ (id)objectForKey:(NSString *)key
{
    return [weakDictionary objectForKey:key];
}

@end

测试代码:

//
//  AppDelegate.m
//  WeakDic
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "AppDelegate.h"
#import "WeakDictionary.h"
#import "YXGCD.h"
#import "Model.h"

@interface AppDelegate ()

@property (nonatomic, strong) Model    *model;
@property (nonatomic, strong) GCDTimer *timer;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // 创建临时model
    Model *tmp = [Model new];
    
    // 注册弱引用对象
    REGISTER_WEAK_OBJECT(tmp, @"Model");
    
    // 通过属性持有这个临时model
    self.model = tmp;
    
    // 7s之后这个属性持有另外一个model(原先model被释放了)
    [[GCDQueue mainQueue] execute:^{
        self.model = [Model new];
    } afterDelay:NSEC_PER_SEC*7];
    
    // 启动定时器监测临时model
    _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
    [_timer event:^{
        NSLog(@"%@", GET_WEAK_OBJECT(@"Model"));
    } timeInterval:NSEC_PER_SEC];
    [_timer start];
    
    return YES;
}

@end

测试图例:

至于为何要设计出这么一种单例出来,这种不增加对象引用计数却能持有对象的单例,你想想能有什么用处呢:)

原文地址:https://www.cnblogs.com/YouXianMing/p/3889422.html