IOS - 延迟执行performSelector和取消延迟执行cancelPreviousPerformRequestsWithTarget
2015-08-18 21:58 HermitCarb 阅读(7531) 评论(0) 编辑 收藏 举报IOS开发时可能会想用到延时执行一个函数。学会用这个函数有时会让代码简单很多。
下文出现的self均指当前页面控制器(ViewController)
基本方法:
1 @interface NSObject (NSDelayedPerforming) 2 3 //设置延迟执行,delay单位为秒 4 - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes; 5 6 - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; 7 8 //取消已设置的延迟执行 9 + (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument; 10 11 + (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget; 12 13 @end
如若设置下面的延迟执行方法:
1 [self performSelector:@selector(didRuninCurrModel:) withObject:[NSNumber numberWithBool:YES] afterDelay:3.0f]; 2 3 [self performSelector:@selector(didRuninCurrModelNoArgument) withObject:nil afterDelay:3.0f];
若取消对应的延迟执行方法可用下面方法:
1 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModel:) object:[NSNumber numberWithBool:YES]]; 2 3 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModelNoArgument) object:nil];
需要注意的是参数的一致性,如下面的取消无法实现:
1 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModel:) object:[NSNumber numberWithBool:NO]]; 2 3 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModel:) object:nil];
下面方法可以一次取消所有的延迟执行:
1 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 2 3 [[self class] cancelPreviousPerformRequestsWithTarget:self];
注意:设置延迟执行可能会导致内存泄漏:
(这个我也不是特别懂,不能说没遇到过,只是现在的水平还达不到那个高度)
搜集网上的资料说:当页面需要dealloc时,若延迟函数还没有执行会引发内存泄漏。
个人认为如果像这样设置延迟执行:
1 [self performSelector:@selector(function) withObject:self afterDelay:30.0f];
若在页面需要dealloc时没有执行延迟函数,从self的引用计数来看应该会出现内存泄漏。
但是不清楚当参数withObject:nil 时会不会改变self的引用计数。
另外,我在一次练习中用到了这个延迟执行,但是,最终失败了,分享一下我当时的做法和现在的一些想法。
TestApp是一个NavigationController控制的二级页面。当点击首页的TableViewCell会跳转到第二级页面。然后我的延迟执行是在第二级页面设置的。延迟执行设置和执行方面正常,但当我设置好延迟执行,返回主页然后再进入该第二级页面,无法取消之前设置的延迟执行。
NavigationController控制的页面跳转,是把页面控制器放到一个栈里,根据前进还是返回进行入栈和出栈的。后来分析了下,像上面,我第二次进入第二级页面已经不是第一次进入的那个第二级页面了,所以不能取消第一次设置的延迟执行。但是延迟执行能够执行成功,则是说明第一次的那个第二级页面虽然出栈了但没有被dealloc掉,这个应该是因为设置延迟执行会增加页面的引用计数,而和设置引用计数时有没有设置withObject:self 或者withObject:nil 没有关系。
不知道我的想法对不对,大神不要嘲笑,欢迎指导!