在實際開發過程中,使用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已經被銷燬了,那麼就不再執行對應的邏輯了。避免資源浪費,提高代碼健壯性。
更多技術乾貨文章可以掃描下方二維碼: