This article was first published on my personal blog: blog.shenyuanluo.com. Welcome to subscribe if you like.
Consider the following code. What is the final output?
- Example 1:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) withObject:nil]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
One, two, three, four
- The reason:because
performSelector:withObject:
The specified selector is executed immediately on the current thread.
- Output result:
- Example (2) :
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) withObject:nil afterDelay:0]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
One, two, four
- The reason:because
performSelector:withObject:afterDelay:
It registers a timer in the RunLoop, and in the child thread, the RunLoop is not enabled (by default), so it does not output3
. The official website API is explained as follows:
- Output result:
- Example 3:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) withObject:nil afterDelay:0]; [[NSRunLoop currentRunLoop] run]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
One, two, three, four
- The reason:Due to the
[[NSRunLoop currentRunLoop] run];
The RunLoop object corresponding to the current child thread is created and started, so it can be executedtest
Methods; andtest
After execution, the timer registered in the RunLoop is invalid, so you can still output4
⑥ Examples
- Output result:
- Example 4:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) onThread:[NSThread currentThread] withObject:nil waitUntilDone:YES]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
One, two, three, four
- The reason:because
performSelector:onThread:withObject:waitUntilDone:
Executes on the specified thread, and executes according to the parameterswait
Deal with it. Pass it hereYES
Indicates that it will be blocked immediatelySpecified threadAnd executes the specifiedselector
. The official API is explained as follows:
- Output result:
- Example 5:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
One, two, four
- The reason:because
performSelector:onThread:withObject:waitUntilDone:
Executes on the specified thread, and executes according to the parameterswait
Deal with it. Pass it hereNO
Indicates that the block is not immediately blockedSpecified threadIt will beselector
Added to the specified threadRunLoopWaiting for an opportunity to execute. (In this example, the child thread RunLoop is not started, so there is no output3
The official website API is explained as follows:
- Output result:
- Example 6:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO]; [[NSRunLoop currentRunLoop] run]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
1,2,3
- The reason:Due to the
[[NSRunLoop currentRunLoop] run];
The RunLoop object corresponding to the current child thread has been created and started, so it is ready to executetest
Methods; buttest
The RunLoop does not end after the method is executed. (Using this startup method, the RunLoop will continue running, processing data from the input source during this time, and will run in theNSDefaultRunLoopMode
Repeat the call in moderunMode:beforeDate:
Method) so cannot continue output4
.
- Output result:
- Example 7:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO]; [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
1,2,3
- The reason:Due to the
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
The RunLoop object corresponding to the current child thread has been created and started, so it is ready to executetest
Methods; buttest
The RunLoop does not end after the method is executed. (With this startup method, you can set a timeout, and the RunLoop will run until the timeout expires, during which time the RunLoop will process data from the input source, and will run in theNSDefaultRunLoopMode
Repeat the call in moderunMode:beforeDate:
Method) so cannot continue output4
.
- Output result:
- Examples today:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"1 - % @", [NSThread currentThread]); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"2 - % @", [NSThread currentThread]); [self performSelector:@selector(test) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO]; [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; NSLog(@4 - % @ "", [NSThread currentThread]); }); } - (void)test { NSLog(@"3 - % @", [NSThread currentThread]); } Copy the code
- Output result:
One, two, three, four
- The reason:Due to the
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
The RunLoop object corresponding to the current child thread has been created and started, so it is ready to executetest
Methods; andtest
The RunLoop terminates immediately after the method is executed. (With this startup, the RunLoop runs once until the timeout expires or the firstinput source
Is processed, RunLoop exits) so you can continue output4
.
- Output result:
Summary:
- So we’re going to use performSelector
- The common method to perform is the nsobject. h header:
- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; Copy the code
- Perform, which is the method under the nsrunloop. h header:
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes; - (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay; Copy the code
- We can specify threads’ perform, which is the method under the NSThread header:
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array; - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array; - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait; - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg; Copy the code
- RunLoop Exit:
- use
- (void)run;
When started, the RunLoop runs forever, processing data from the input source, and running in theNSDefaultRunLoopMode
Repeat the call in moderunMode:beforeDate:
Methods; - use
- (void) runUntilDate (limitDate NSDate *);
Start, you can set a timeout period, and the RunLoop will run until the timeout period is reached, during which time the RunLoop will process data from the input source, and will also run inNSDefaultRunLoopMode
Repeat the call in moderunMode:beforeDate:
Methods; - use
- (void)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;
On startup, the RunLoop will run once, and either the timeout expires or the first oneinput source
Is processed, the RunLoop exits.
- use
- See this blog post for more information on how NSRunLoop exits
reference
- Exit method of NSRunLoop