需求
在某些时候,需要对请求进行延时处理。
例如:
- 对某条评论进行点赞,如果用户无限点击赞/取消赞按钮,就会无限发出请求。这是一种不合理的做法。通常采用一种折中的办法,在点击按钮一段时候(例如1秒)后才真正发出请求。
例如:在切换不同Tab时候要调用不同的API
解决方案
- 在UI层面,添加一个分类
/**
* @brief 在 delay秒之后,执行action操作
*
* @param action 执行的操作
* @param newObject 参数
* @param delay 延时时间
*/
-(void)debounceAction:(SEL)action object:(id)newObject delay:(NSTimeInterval)delay;
实现
+(void)debounceForTarget:(id)target action:(SEL)action object:(id)newObject delay:(NSTimeInterval)delay{
if(target == nil || action == nil){ return;}
// NSString *selectorString = NSStringFromSelector(action);
// id oldObj = objc_getAssociatedObject(target,[selectorString UTF8String]); // WRONG
id oldObj = objc_getAssociatedObject(target,action);
//NSLog(@"oldObj:%@",oldObj);
[NSObject cancelPreviousPerformRequestsWithTarget:target selector:action object:oldObj];
// Why do we need to retain this object???
objc_setAssociatedObject(target, action, newObject, OBJC_ASSOCIATION_RETAIN);
// NSString *selectorString2 = NSStringFromSelector(action);
// id newObj = objc_getAssociatedObject(target,[selectorString2 UTF8String]);
//id newObj = objc_getAssociatedObject(target,@selector(action));
//NSLog(@"newObj:%@",newObj);
[target performSelector:action withObject:newObject afterDelay:delay];
}
-(void)debounceAction:(SEL)action object:(id)newObject delay:(NSTimeInterval)delay{
[[self class] debounceForTarget:self action:action object:newObject delay:delay];
}
+(void)debounceForTarget:(id)target action:(SEL)action objectToBeCancelled:(id)oldObject objectToBePerform:(id)newObject delay:(NSTimeInterval)delay{
NSAssert(target != nil, @"target 不能为nil", nil);
// !!! call this method may cancel other actions ,
//[NSObject cancelPreviousPerformRequestsWithTarget:target];
[NSObject cancelPreviousPerformRequestsWithTarget:target selector:action object:oldObject];
// [NSObject cancelPreviousPerformRequestsWithTarget:target selector:action object:object];
// the Argument [object] may be different with last performrequest,if so,the last perform will not be cancelled.
[target performSelector:action withObject:newObject afterDelay:delay];
}
Demo
别人的git
NSObject-DebounceDemo.
- 在http request里增加time之类的想法,改动便捷性都不合适。