[实践]iOS数组Delegate解引用

如果对您有帮助还请 "赞" 一下哈, 有问题可留言或加QQ群:323276186

背景:#

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

问题:#

那么问题来了, 数组是强引用持有对象的, 所以会造成持有的对象不能释放问题. (例如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)listener;

@end

@implementation SYLocationManager

- (void)addListener:(id)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 delegate;

@end

你可能感兴趣的:([实践]iOS数组Delegate解引用)