在实际开发过程中,使用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已经被销毁了,那么就不再执行对应的逻辑了。避免资源浪费,提高代码健壮性。
更多技术干货文章可以扫描下方二维码: