子线程Timer和Runloop的问题

SkylinePoint 2016-11-13 10:59:27
在ViewController中建 NSTimer和NSTheard两个属性,在子线程中开启timer,并加入Runloop中。当我关闭timer和theard后,返回上个界面的dealloc方法不走。请问各位大神这是什么原因(timer和theard全为nil还是不能走dealloc)



下面是代码




#import "ShowViewController.h"

@interface ShowViewController ()

//
@property (nonatomic,strong) NSTimer *timer;

//
@property (nonatomic,strong) NSThread *thread;


@end

@implementation ShowViewController

- (void)dealloc{
NSLog(@"销毁");
}

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(back)];
self.navigationItem.leftBarButtonItem = leftBtn;

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
__weak typeof(self) weakSelf = self;
self.thread = [[NSThread alloc] initWithTarget:weakSelf selector:@selector(openTimer) object:nil];
[_thread start];

}

// 返回
- (void)back{

if (_timer && _thread) {
[self performSelector:@selector(deleteTimer) onThread:_thread withObject:nil waitUntilDone:NO];
[self performSelector:@selector(stopThread) onThread:_thread withObject:nil waitUntilDone:NO];
_thread = nil;
}
NSLog(@"%@",self);
[self.navigationController popViewControllerAnimated:YES];
NSLog(@"%@",self);
}

// 停止线程
- (void)stopThread{

CFRunLoopStop(CFRunLoopGetCurrent());
}

//
- (void)openTimer{
@autoreleasepool {
__weak typeof(self) sSelf = self;
if (!_timer) {
self.timer = [NSTimer timerWithTimeInterval:1 target:sSelf selector:@selector(click) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];

}
}

}

- (void)click{
NSLog(@"1");
}

- (void)deleteTimer{
[self.timer invalidate];
self.timer = nil;

}


...全文
700 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
SkylinePoint 2018-06-21
  • 打赏
  • 举报
回复
翻到老帖子,自己说下,必须在定时器开启的线程中关闭定时器。
f6784 2017-06-13
  • 打赏
  • 举报
回复
@麒丞 用了一下runUntilDate方法,确实在停止runloop后,还能执行后面的代码。想请教一下,为什么这里如果用了run之后就一直阻塞呢?
f6784 2017-06-13
  • 打赏
  • 举报
回复
你好,我遇到的问题和你的有相同的地方。不过也有一点不同。我在子线程开启timer后,手动打开runloop后,就一直阻塞在那里了
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"%@",[NSThread currentThread]);
    
    __weak __typeof(self) weakSelf = self;
    
    //创建子线程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
            __strong __typeof(weakSelf) strongSelf = weakSelf;
            
            if (strongSelf) {
                strongSelf.thread1 = [NSThread currentThread];
                [strongSelf.thread1 setName:@"线程A"];
                
                //在子线程中创建NSTimer
                strongSelf.threadTimer = [NSTimer timerWithTimeInterval:1 target:strongSelf selector:@selector(timerAction) userInfo:nil repeats:YES];
                
                //将NSTimer加入到子线程的RunLoop中
                NSRunLoop *runloop = [NSRunLoop currentRunLoop];
                [runloop addTimer:strongSelf.threadTimer forMode:NSDefaultRunLoopMode];
                
                //手动启动RunLoop
                [runloop run];
                
                NSLog(@"###########");
                
                [NSThread sleepForTimeInterval:2];
                
                [strongSelf.threadTimer invalidate];
            }

    });

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    if (self.threadTimer) {
        
        [self.threadTimer invalidate];
        self.threadTimer = nil;
    }
}

}
[runloop run]; 后面的代码 [strongSelf.threadTimer invalidate];根本就没有执行,所以就没法停止timer,而调用touchesBegan:withEvent:方法里的[self.threadTimer invalidate];才可以停止timer。请问怎么解决呢?
f6784 2017-06-13
  • 打赏
  • 举报
回复
你好,我遇到的问题和你的有相同的地方。不过也有一点不同。我在子线程开启timer后,手动打开runloop后,就一直阻塞在那里了 - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%@",[NSThread currentThread]); __weak __typeof(self) weakSelf = self; //创建子线程 dispatch_async(dispatch_get_global_queue(0, 0), ^{ __strong __typeof(weakSelf) strongSelf = weakSelf; if (strongSelf) { strongSelf.thread1 = [NSThread currentThread]; [strongSelf.thread1 setName:@"线程A"]; //在子线程中创建NSTimer strongSelf.threadTimer = [NSTimer timerWithTimeInterval:1 target:strongSelf selector:@selector(timerAction) userInfo:nil repeats:YES]; //将NSTimer加入到子线程的RunLoop中 NSRunLoop *runloop = [NSRunLoop currentRunLoop]; [runloop addTimer:strongSelf.threadTimer forMode:NSDefaultRunLoopMode]; //手动启动RunLoop [runloop run]; NSLog(@"###########"); [NSThread sleepForTimeInterval:2]; [strongSelf.threadTimer invalidate]; } }); } [runloop run]; 后面的代码根本就没有执行。请问怎么解决?
麒丞 2016-11-23
  • 打赏
  • 举报
回复
原因在于[[NSRunLoop currentRunLoop] run];没有停止,可以使用runUntilDate
麒丞 2016-11-23
  • 打赏
  • 举报
回复
可以不用runloop不开线程,直接使用timer的这个方法

-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self deleteTimer];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    __weak typeof(self) weakSelf = self;
//    self.thread = [[NSThread alloc] initWithTarget:weakSelf selector:@selector(openTimer) object:nil];
//    [_thread start];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(click) userInfo:nil repeats:YES];

}
SkylinePoint 2016-11-16
  • 打赏
  • 举报
回复
没什么用。。
SkylinePoint 2016-11-14
  • 打赏
  • 举报
回复
坐等大神解答
淡念- 2016-11-14
  • 打赏
  • 举报
回复
销毁timer 放到主线程中。[self performSelector:@selector(deleteTimer) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO];

29,027

社区成员

发帖
与我相关
我的任务
社区描述
主要讨论与iOS相关的软件和技术
社区管理员
  • iOS
  • 大熊猫侯佩
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧