使用NSTimer出现的问题
2016-03-24 00:00
274 查看
摘要: 去年封的一个图片轮播的, 这两天在忙着给重新封装一下, 增加更多的方法, 有更多个性化的设置, 增加了网络请求图片的轮播. 重新封装, 这个过程还算顺利, 但是到计时器那块卡住了.
WHImagePlayer图片轮播和图片浏览器: https://github.com/hell03W/WHImagePlayer, 欢迎star支持一下, 如果有任何问题欢迎issue给我.
问题是这样的:
简单来说, 其实就是计时器, 我用的NSTimer, 是在一个自定义view中创建NSTimer的, 如果是在控制器中, 可以在viewWillDisappear:中执行NSTimer的
经过在网上查找资料, 和自己的思考, 最终总结了几种可行方案:
方案一:
如下代码所示, 使用
方案2:
使用一个假冒的对象作为target. 原理也不复杂, 创建一个类, 让新的类拥有self的弱引用, 通过这个类的方法, 将需要作为target的
上代码:
WHTimerTarget.h
WHTimerTarget.m
如上代码所示, 就是新的类, 伪target的全部代码. 使用的方法有两种, 如下:
写在后面的:
目前为止, 我只发现这两种比较好用的方法, 如果谁有更好的方案, 欢迎留言交流 .
使用NSTimer出现的问题
去年封的一个图片轮播的, 这两天在忙着给重新封装一下, 增加更多的方法, 有更多个性化的设置, 增加了网络请求图片的轮播. 重新封装, 这个过程还算顺利, 但是到计时器那块卡住了.WHImagePlayer图片轮播和图片浏览器: https://github.com/hell03W/WHImagePlayer, 欢迎star支持一下, 如果有任何问题欢迎issue给我.
问题是这样的:
简单来说, 其实就是计时器, 我用的NSTimer, 是在一个自定义view中创建NSTimer的, 如果是在控制器中, 可以在viewWillDisappear:中执行NSTimer的
invalidate方法, timer对象是可以被正常销毁的, 但是在自定义的view里面没有那样的方法! 有人会说可以将target设置成
__weak类型的就可以了嘛 ! 我也是那样认为的, 可是试验证明, 那样是不行的(要是那么简单, 也没必要写个blog来记录了).
经过在网上查找资料, 和自己的思考, 最终总结了几种可行方案:
方案一:
如下代码所示, 使用
dispatch_after可以完美解决, 但是需要注意的是, 在block内部, 使用
self时候必须使用weakSelf, 如果直接使用self, 还是不会被释放掉的.
__weak typeof(self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [UIView animateWithDuration:0.3 animations:^{ weakSelf.imageScrollView.contentOffset = CGPointMake(weakSelf.width*2, 0); } completion:^(BOOL finished) { if (finished) { [weakSelf scrollViewDidEndDecelerating:weakSelf.imageScrollView]; [weakSelf setupTimer]; } }]; });
方案2:
使用一个假冒的对象作为target. 原理也不复杂, 创建一个类, 让新的类拥有self的弱引用, 通过这个类的方法, 将需要作为target的
"self"和要执行的方法的名字
"selector", 传入新的类内部, 在新的类内部, 调用
"self"的
"selector"方法, 在自定义view的NSTimer方法中调用新的类的调用外部类方法的方法.
上代码:
WHTimerTarget.h
#import <Foundation/Foundation.h> @interface WHTimerTarget : NSObject /**1. 调用这个方法 传入target和selector和时间, 就会间隔timeInterval秒执行target的selector方法. 内部使用NSTimer实现, 主要是为了解决, NSTimer会出现循环引用的问题 */ + (void)addTarget:(id)target selector:(SEL)selector timeInterval:(NSTimeInterval)timeInterval; /// 2. 如果如要NSTimer写在本类外面, 可以使用这个方法 + (instancetype)timerTarget:(id)target selector:(SEL)selector; - (void)timerDidFire:(NSTimer *)timer; @end
WHTimerTarget.m
#import "WHTimerTarget.h" @implementation WHTimerTarget { __weak id _target; SEL _selector; } - (instancetype)initWithTarget:(id)target selector:(SEL)selector { self = [self init]; _target = target; _selector = selector; return self; } + (instancetype)timerTarget:(id)target selector:(SEL)selector { return [[self alloc] initWithTarget:target selector:selector]; } - (void)timerDidFire:(NSTimer *)timer { if(_target) { [_target performSelector:_selector withObject:timer]; } else { [timer invalidate]; } } + (void)addTarget:(id)target selector:(SEL)selector timeInterval:(NSTimeInterval)timeInterval { id timerTarget = [[self alloc] initWithTarget:target selector:selector]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:timerTarget selector:@selector(timerDidFire:) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; } @end
如上代码所示, 就是新的类, 伪target的全部代码. 使用的方法有两种, 如下:
1, 使用方法: id target = [TimerTarget timerTarget:<#self#> selector:@selector(<#automaticScroll:#>)]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:<#self.autoScrollTimeInterval#> target:target selector:@selector(timerDidFire:) userInfo:nil repeats:YES]; 2, 使用方法: [TimerTarget addTarget:<#self#> selector:@selector(<#automaticScroll:#>) timeInterval:<#3#>];
写在后面的:
目前为止, 我只发现这两种比较好用的方法, 如果谁有更好的方案, 欢迎留言交流 .
相关文章推荐
- 2016淘宝首页今日改版,细说淘宝首页设计变化史
- topdownCar 例子
- 推荐一些C#相关的网站、资源和书籍
- 企业工商信息数据接口
- Gradle sync failed: Plugin is too old,
- duplicate symbol _OBJC_CLASS_$_LYPersonModifyView
- mysql创建、删除、重建、删除索引的操作命令的一些总结
- union和union all的区别
- 线程池原理
- 单例模式
- ScrollView嵌套ListView的解决方案
- 判断 网络地址 是否合法的正则,需要的可以参考下,支持IPV6格式的判断
- android 实现FTPServices 文件传输,支持IPV6
- synchronized锁普通方法和锁静态方法
- PHP 中获取当前时间[Datetime Now]
- js、javascript操作json总结
- ECshop Strict Standards: Only variables should be passed by reference in
- 响应式状态时的jqprint打印
- lodop打印技巧与注意事项
- bootstrap和angular.js技术要求