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