performSelector 和NSTimer使用注意事项

一、performSelectorXXX之类的方法

1、performSelectorOnMainThread:withObject:waitUntilDone:

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

在主线程上执行指定的方法,使用默认的模式(NSDefaultRunLoopMode)。
默认的模式指:主线程中的方法进行排队,是一个循环队列,并且循环执行。
参数:
aSelector:要在主线程执行的方法,该方法不能有返回值,并且只能有一个参数。
arg:要传递的参数,如果无参数,就设为nil
wait:要执行的aSelector方法,是否马上执行。
如果设置为YES:等待当前线程执行完以后,主线程才会执行aSelector方法;
设置为NO:不等待当前线程执行完,就在主线程上执行aSelector方法。
如果,当前线程就是主线程,那么aSelector方法会马上执行。

该方法用途:因为iPhone编程,对UI的修改,只能在主线程上执行。可以用该方法来完成UI的修改。

2、performSelector:withObject:afterDelay:

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay

在当前线程中执行指定的方法,使用默认模式,并指定延迟。
参数:
aSelector:指定的方法。含义同上,不在赘述。
anArgument:同上
delay:指定延迟时间(秒)。

3、performSelector
我们常常用到以下3个方法,分别为:

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

更多参数可以封装字典dictionary再传。

二、NSTimer

先说一下,初始化方法

+ scheduledTimerWithTimeInterval:invocation:repeats:
+ scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:

这两个是创建一个定时器,并自动加入到当前运行循环中,即我们可以这样去理解,初始化了一个定时器时,在(NSTimeInterval)seconds 时间之后,自动启动定时器。

但而以下两个初始化方法这不一样:

+ timerWithTimeInterval:invocation:repeats:
+ timerWithTimeInterval:target:selector:userInfo:repeats:

这两个同样是创建,但没有加入到运行循环中,需要手动添加,如下:

_timer=[NSTimer timerWithTimeInterval:10 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];
 //必须手动加入到当前循环中去
NSRunLoop *runloop=[NSRunLoop currentRunLoop];
[runloop addTimer:_timer forMode:NSDefaultRunLoopMode];

三、代码验证

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //1、在主线程执行调用
    [self performSelector:@selector(performOnMainThread) withObject:nil afterDelay:3];
    
    
    
    [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(scheduledTimerOnMainThread) userInfo:nil repeats:YES];
    
    
    //  要让 timerWithTimeInterval 这个定时器执行,不行手动加到必须手动加入到当前循环中去
    /**
     *  [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerWithTimeMethod) userInfo:nil repeats:YES];
    
     *   NSRunLoop *runloop=[NSRunLoop currentRunLoop];
     *   [runloop addTimer:_timer forMode:NSDefaultRunLoopMode];
     *
     */
    
    
    
    [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerWithTimeOnMainThread) userInfo:nil repeats:YES];
    
//    2、在子线程执行调用
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        [self performSelector:@selector(performOnSubThread) withObject:nil afterDelay:3];
        
        
        [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(scheduledTimerOnSubThread) userInfo:nil repeats:YES];
        
        
        [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(timerWithTimeOnSubThread) userInfo:nil repeats:YES];
    });
    
    
}

#pragma mark - 延迟执行指定方法
- (void)performOnMainThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主线程":@"子线程";
    NSLog(@"performOnMainThread 方法在 %@ 执行",thread);
    NSLog(@"-------------------------------------------------");
}


- (void)performOnSubThread {
    
    NSString *thread = [NSThread isMainThread] == 1 ? @"主线程":@"子线程";
    NSLog(@"performonSubThread 方法在 %@ 执行",thread);
    NSLog(@"-------------------------------------------------");
}


- (void)scheduledTimerOnMainThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主线程":@"子线程";
    NSLog(@"scheduledTimerOnMainThread 方法在 %@ 执行",thread);
    NSLog(@"-------------------------------------------------");
}

- (void)scheduledTimerOnSubThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主线程":@"子线程";
    NSLog(@"scheduledTimerOnSubThread 方法在 %@ 执行",thread);
    NSLog(@"-------------------------------------------------");
}

- (void)timerWithTimeOnSubThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主线程":@"子线程";
    NSLog(@"timerWithTimeOnSubThread 方法在 %@ 执行",thread);
    NSLog(@"-------------------------------------------------");
}

- (void)timerWithTimeOnMainThread {
    NSString *thread = [NSThread isMainThread] == 1 ? @"主线程":@"子线程";
    NSLog(@"timerWithTimeOnMainThread 方法在 %@ 执行",thread);
    NSLog(@"-------------------------------------------------");
}


结果输出如下:

2016-08-16 11:30:55.776 performSelector[9788:1950942] performOnMainThread 方法在主线程执行
2016-08-16 11:30:55.777 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:30:55.777 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主线程执行
2016-08-16 11:30:55.778 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:30:58.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主线程执行
2016-08-16 11:30:58.776 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:31:01.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主线程执行
2016-08-16 11:31:01.777 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:31:04.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主线程执行
2016-08-16 11:31:04.777 performSelector[9788:1950942] -------------------------------------------------
2016-08-16 11:31:07.776 performSelector[9788:1950942] scheduledTimerOnMainThread 方法在主线程执行
2016-08-16 11:31:07.776 performSelector[9788:1950942] -------------------------------------------------

四、结论

performSelector:withObject:afterDelay 和
[NSTimer timerWithTimeInterval:invocation:repeats:]
放在在子线程中指定的@selecter()不会执行,主线程中可正常使用。因此必须保证调用是在主线程中。因此,可以使用GCD的方式,将此调用放在主线程中执行:
dispatch_async(dispatch_get_main_queue(), ^{ });或者调用
performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

你可能感兴趣的:(performSelector 和NSTimer使用注意事项)