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

所有文章目录:my.oschina.net/ChenTF/blog…

本篇文章地址: my.oschina.net/ChenTF/blog…

如果对您有帮助还请 “赞” 一下哈, 有问题可留言或加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方法来进行遍历移除. 参考: blog.csdn.net/wzf90681982…

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://juejin.im/entry/58a56c5a570c35006b5b83b5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞