iOS内存优化之解决延迟释放

    在实际开发过程中,使用NSTimer 或者 performSelector... afterdelay 在定时器事件未触发的时候,如果返回上一个页面,会由于runloop强持有target,短时间内不会释放。造成内存不能及时释放。而且等到定时器触发事件时会执行已经没有意义的逻辑运算,额外浪费资源。因此内存的及时释放也是app内存优化的一个点。NSTimer的之前的博客已经实现,这里就不多说了,这里以以下代码为例。

@interface NSObject (JKBasicProvider)

- (void)jk_performSelector:(SEL)aSelector
                withObject:(nullable id)anArgument
                afterDelay:(NSTimeInterval)delay
                   inModes:(NSArray<NSRunLoopMode> *)modes;

- (void)jk_performBlock:(void(^)(void))block
             withObject:(id)anArgument
             afterDelay:(NSTimeInterval)delay
                inModes:(NSArray<NSRunLoopMode> *)modes;

- (void)jk_performSelector:(SEL)aSelector
                withObject:(nullable id)anArgument
                afterDelay:(NSTimeInterval)delay;

- (void)jk_performBlock:(void(^)(void))block
             withObject:(nullable id)anArgument
             afterDelay:(NSTimeInterval)delay;
@end
#import "NSObject+JKBasicProvider.h"

@interface JKPerformSelectorTarget : NSObject

@property (nonatomic, weak) id actionTarget;
@property (nonatomic, weak) id actionArgument;
@property (nonatomic, assign) SEL actionSelector;
@property (nonatomic, copy) void(^actionBlock)(void);

@end

@implementation JKPerformSelectorTarget

- (instancetype)initWithSelector:(SEL)selector
                          target:(id)target
                        argument:(nullable id)argument
{
    self = [super init];
    if (self) {
        self.actionSelector = selector;
        self.actionTarget = target;
        self.actionArgument = argument;
        self.actionBlock = nil;
    }
    return self;
}

- (instancetype)initWithBlock:(void(^)(void))actionBlock
                       target:(id)target
                     argument:(nullable id)argument
{
  self = [super init];
    if (self) {
        self.actionTarget = target;
        self.actionArgument = argument;
        self.actionBlock = nil;
    }
    return self;
}

- (void)performSelectorAction:(id)argument
{
    if (self.actionTarget) {
        if (self.actionBlock) {
            self.actionBlock();
        } else {
            IMP imp = [self.actionTarget methodForSelector:self.actionSelector];
            void (*func)(id, SEL,id) = (void *)imp;
            func(self.actionTarget, self.actionSelector,argument);
        }
    }
}

@end

@implementation NSObject (JKBasicProvider)

- (void)jk_performSelector:(SEL)aSelector
                withObject:(nullable id)anArgument
                afterDelay:(NSTimeInterval)delay
                   inModes:(NSArray<NSRunLoopMode> *)modes
{
    if (delay > 0) {
        JKPerformSelectorTarget *target = [[JKPerformSelectorTarget alloc] initWithSelector:aSelector target:self argument:anArgument];
        [target performSelector:@selector(performSelectorAction:) withObject:anArgument afterDelay:delay inModes:modes];
    } else {
        [self performSelector:aSelector withObject:anArgument afterDelay:delay inModes:modes];
    }
}

- (void)jk_performBlock:(void(^)(void))block
             withObject:(id)anArgument
             afterDelay:(NSTimeInterval)delay
                inModes:(NSArray<NSRunLoopMode> *)modes
{
    JKPerformSelectorTarget *target = [[JKPerformSelectorTarget alloc] initWithBlock:block target:self argument:anArgument];
     [target performSelector:@selector(performSelectorAction:) withObject:anArgument afterDelay:delay inModes:modes];
}

- (void)jk_performSelector:(SEL)aSelector
                withObject:(nullable id)anArgument
                afterDelay:(NSTimeInterval)delay
{
    if (delay > 0) {
       JKPerformSelectorTarget *target = [[JKPerformSelectorTarget alloc] initWithSelector:aSelector target:self argument:anArgument];
        [target performSelector:@selector(performSelectorAction:) withObject:anArgument afterDelay:delay];
    } else {
        [self performSelector:aSelector withObject:anArgument afterDelay:delay];
    }
}

- (void)jk_performBlock:(void(^)(void))block
             withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay
{
    JKPerformSelectorTarget *target = [[JKPerformSelectorTarget alloc] initWithBlock:block target:self argument:anArgument];
    [target performSelector:@selector(performSelectorAction:) withObject:anArgument afterDelay:delay];
}
@end

原理就是通过中介者,用一个较小内存对象替换较大内存内对象,让较大内存对象能够及时释放同时在定时器响应的事件到来时,如果真正的target已经被销毁了,那么就不再执行对应的逻辑了。避免资源浪费,提高代码健壮性。
更多技术干货文章可以扫描下方二维码:
在这里插入图片描述

发布了231 篇原创文章 · 获赞 110 · 访问量 60万+

猜你喜欢

转载自blog.csdn.net/HHL110120/article/details/102760931