1、Apple的源码
2、练习demo
//
// ViewController.m
// RunloopTest
//
// Created by super on 2020/7/29.
// Copyright © 2020 super. All rights reserved.
//
#import "ViewController.h"
#import "MyCell.h"
@interface ViewController ()<NSPortDelegate,UITableViewDataSource>
/** tableView 用于测试滑动后runloop mode的变化 */
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
@implementation ViewController
/** 关于iOS runloop的优秀资料
https://opensource.apple.com/source/CF/CF-1153.18/CFRunLoop.c.auto.html
https://blog.ibireme.com/2015/05/18/runloop/
https://github.com/ming1016/study/wiki/CFRunLoop
https://v.youku.com/v_show/id_XODgxODkzODI0.html
*/
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellReuseIdentifier:@"MyCell"];
//runloop1
// [self runloop1];
//runloop2
// [self runloop2];
//runloop3
// [self runloop3];
}
/// 普通的NSTimer与runloop
- (void)runloop1
{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(runloop1Action) userInfo:nil repeats:YES];
/* 滑动tableView,系统切换到UITrackingRunLoopMode。 NSRunLoopCommonModes 包含此模式,所以timer正常执行,
* NSDefaultRunLoopMode 滑动tableView timer停止执行 */
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
///子线程线程保活
- (void)runloop2
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object: nil];
[thread start];
}
/// performSelector:onThread:withObject:waitUntilDone 与 runloop
- (void)runloop3
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(enterPoint) object:nil];;
[thread start];
NSArray *symbols = [NSThread callStackSymbols];
NSLog(@"symbols--->%@",symbols);
/** performSelector:等方法内部会创建了一个NSTimer,并添加到当前线程的runloop中 */
[self performSelector:@selector(doSome) onThread:thread withObject:nil waitUntilDone:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];
return cell;
}
#pragma mark - Action
- (void)runloop1Action
{
NSLog(@"--->runloop1Action");
}
- (void)newThread
{
NSLog(@"--->newThread");
@autoreleasepool {
//子线程创建timer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(increseCounter:) userInfo:nil repeats:YES];
//子线程开启runloop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
- (void)increseCounter:(NSTimer *)timer
{
NSLog(@"--->increseCounter");
}
- (void)enterPoint
{
@autoreleasepool {
[[NSThread currentThread] setName:@"super"];
[[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
/* run方法一定要执行,否则报错
Terminating app due to uncaught exception 'NSDestinationInvalidException', reason: '*** -[ViewController performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform */
[[NSRunLoop currentRunLoop] run];
}
}
- (void)doSome
{
NSLog(@"--->doSome");
}
- (IBAction)buttonAction:(id)sender {
//点击按钮打印线程堆栈
NSArray *symbols = [NSThread callStackSymbols];
NSLog(@"symbols--->%@",symbols);
}
@end