[实践]iOS数组Delegate解引用实践

更好的方式:


NSHashTable == 弱引用版的NSSet
NSMapTable == 弱引用版的NSDictionary

旧文


背景:

有一个单例类, 提供了定位服务, 然后通过数组来持有代理对象, 以达到多个代理效果.

问题:

那么问题来了, 数组是强引用持有对象的, 所以会造成持有的对象不能释放问题. (例如VC已经关闭, 但是还被数组持有, 所以不会走dealloc方法)

解决思路:

创建一个NSObject对象(暂命名为weakObject), weak持有代理对象(vc), 然后单例类的数组持有该weakObject对象. 这样vc就能正常释放了.

注意点:

  1. 其实是把强持有vc的问题转换给了weakObject, 所以数组中weakObject对象还是会越来越多. 所以需要在调用weakObject.delegate时进行判断. 如果weakObject.delegate==nil,则把weakObject从单例类的数组中移除.

  2. 从数组中移除元素时, 不能再for循环内进行, 否则会crash. 可使用NSArray的enumerateObjectsUsingBlock方法来进行遍历移除. 参考: http://blog.csdn.net/wzf906819823/article/details/47069205

DEMO:

单例类:

@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

弱引用类

@interface SYLocationWeakTarget : NSObject

@property (nonatomic, weak) id<SYLocationListener> delegate;

@end

转载于:https://my.oschina.net/ChenTF/blog/840239

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值