標籤:style blog http color 使用 strong io for
設計一個不強引用對象的單例字典
大家都知道,使用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
測試圖例:
至於為何要設計出這麼一種單例出來,這種不增加對象引用計數卻能持有對象的單例,你想想能有什麼用處呢:)