设计一个不强引用对象的单例字典
设计一个不强引用对象的单例字典
大家都知道,使用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
测试图例:
至于为何要设计出这么一种单例出来,这种不增加对象引用计数却能持有对象的单例,你想想能有什么用处呢:)