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