NSHashTable == 弱引用版的NSSet
NSMapTable == 弱引用版的NSDictionary數組
有一個單例類, 提供了定位服務, 而後經過數組來持有代理對象, 以達到多個代理效果.atom
那麼問題來了, 數組是強引用持有對象的, 因此會形成持有的對象不能釋放問題. (例如VC已經關閉, 可是還被數組持有, 因此不會走dealloc方法).net
建立一個NSObject對象(暫命名爲weakObject), weak持有代理對象(vc), 而後單例類的數組持有該weakObject對象. 這樣vc就能正常釋放了.代理
注意點:code
實際上是把強持有vc的問題轉換給了weakObject, 因此數組中weakObject對象仍是會愈來愈多. 因此須要在調用weakObject.delegate時進行判斷. 若是weakObject.delegate==nil,則把weakObject從單例類的數組中移除.對象
從數組中移除元素時, 不能再for循環內進行, 不然會crash. 可以使用NSArray的enumerateObjectsUsingBlock方法來進行遍歷移除. 參考: http://blog.csdn.net/wzf906819823/article/details/47069205blog
單例類:事件
@interface SYLocationManager : NSObject /** * 添加監聽者 * * @param listener 監聽者 */ - (void)addListener:(id<SYLocationListener>)listener; @end @implementation SYLocationManager - (void)addListener:(id<SYLocationListener>)listener { if (!_listenerList) { _listenerList = [[NSMutableArray alloc] init]; } SYLocationWeakTarget *weakTarget = [[SYLocationWeakTarget alloc] init]; weakTarget.delegate = listener; [_listenerList addObject:weakTarget]; } // 事件回調 - (void)notifyLocateSuccess { [self removeAllIncalidDelegate]; for (SYLocationWeakTarget *weakTarget in _listenerList) { if ([weakTarget.delegate respondsToSelector:@selector(locateResult:)]) { [weakTarget.delegate locateResult:TRUE]; } } } // 移除已釋放的代理對象 - (void)removeAllIncalidDelegate { [_listenerList enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { SYLocationWeakTarget *target = (SYLocationWeakTarget *)obj; if (target.delegate == nil) { [_listenerList removeObject:target]; } }]; } @end
弱引用類rem
@interface SYLocationWeakTarget : NSObject @property (nonatomic, weak) id<SYLocationListener> delegate; @end