iOS线程的实现: NSThread

2018-10-22  本文已影响13人  RyderZhang

线程间的通信:
在iOS开发过程中,我们一般在主线程里边进行UI刷新,例如:点击、滚动、拖拽等事件。我们通常把一些耗时的操作放在其他线程,比如说图片下载、文件上传等耗时操作。而当我们有时候在其他线程完成了耗时操作时,需要回到主线程,那么就用到了线程之间的通讯。

NSObject中多线程的方法:

开启后台执行任务的方法
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg

在后台线程中通知主线程执行任务的方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

线程通信
[self performSelector:@selector(function) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];

代码实例NSObjectFunc实现线程间的通信

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *buttonNames = @[@"阻塞主线程", @"看看卡不卡"];
    for (NSInteger i=0; i<buttonNames.count; i++) {
        UIButton *btn=[[UIButton alloc]initWithFrame:CGRectMake(10, 200+70*i, self.view.frame.size.width-20, 30)];
        [btn setTitle:buttonNames[i] forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
        btn.tag=100+i;
        [btn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
}

-(void)buttonClick:(UIButton *)button{
    if (button.tag == 100) {
        //[self needLongTimeFuction];
        
        /*performSelectorInBackground:withObject:
         自动开辟一个子线程,让self在子线程中运行needLongTimeFuction方法
         
         第一个参数:代表执行的方法
         第二个参数:表示执行这个方法需要传的参数

         */
        [self performSelectorInBackground:@selector(needLongTimeFuction) withObject:nil];
        
        //[NSThread mainThread]    取到主线程  number=1代表主线程
        //[NSThread currentThread] 取到当前线程
        NSLog(@"%@", [NSThread mainThread]);
        NSLog(@"%@", [NSThread currentThread]);
    }
    
    if (button.tag == 101) {
        NSLog(@"不卡了!!!");
    }
}

#pragma mark - 耗时操作
-(void)needLongTimeFuction{
    
    //注意: 子线程最好放在自动释放池中
    @autoreleasepool {
        NSLog(@"%@", [NSThread currentThread]);
        NSLog(@"耗时操作执行开始!!!");
        //当前线程休眠多长时间,例如模拟请求网络数据
        [NSThread sleepForTimeInterval:60.0];
        NSLog(@"耗时操作执行结束!!!");
        
        
        //耗时操作完成,如果需要刷新UI,必须要在主线程里刷新页面
        //[self reloadCurrentPageUI];
        
        /*
         让self在主线程中执行reloadCurrentPageUI方法
         第一个参数:执行的方法
         第二个参数:执行方法所需要传递的参数
         第三个参数:代表子线程是否需要等待主线程执行完成方法
         */
        //[self performSelectorOnMainThread:@selector(reloadCurrentPageUI) withObject:nil waitUntilDone:YES];
        
        /*让self在X线程中执行reloadCurrentPageUI的方法
         第一个参数:执行的方法
         第二个参数:在哪个线程中执行
         第三个参数:执行方法需要传递的参数
         第四个参数:代表当前线程是否需要等待X线程执行完成
         */
        [self performSelector:@selector(reloadCurrentPageUI) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
    }
}

#pragma mark - 刷新界面UI
-(void)reloadCurrentPageUI{
    NSLog(@"UI刷新成功!!!");
}

NSThread Objective-C的线程类

1)创建线程,并自动执行
[NSThread  detachNewThreadSelector:@selector(doSomeThing) toTarget:self withObject:nil];

2)创建线程,不自动执行
[[NSThread  alloc] initWithTarget:self selector:@selector(doSomeThing) object:nil];

3)设置线程名
thread.name = @"另一个线程";

4)执行线程
[thread  start];

5)函数内获取当前线程
[NSThread currentThread];

6)获取主线程
[NSThread mainThread];

7)线程休眠
[NSThread sleepForTimeInterval:1.0f];  // 休眠几秒
[NSThread sleepUntilDate:date];  // 休眠到指定时间

8)线程退出
[NSThread exit];

代码实例NSThread实现线程间的通信

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *buttonNames = @[@"阻塞主线程", @"看看卡不卡"];
    for (NSInteger i=0; i<buttonNames.count; i++) {
        UIButton *btn=[[UIButton alloc]initWithFrame:CGRectMake(10, 200+70*i, self.view.frame.size.width-20, 30)];
        [btn setTitle:buttonNames[i] forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
        btn.tag=100+i;
        [btn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
}


-(void)buttonClick:(UIButton *)button{
    if (button.tag == 100) {
        //[self needLongTimeFuction];
        
        
        /*创建一个子线程,让self去执行[self needLongTimeFuction]
         第一个参数:谁去执行这个
         第二个参数:执行哪个方法
         第三个参数:执行方法所需要传递的参数
         注意:这个方法需要手动去开启线程
         */
        //NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(needLongTimeFuction) object:nil];
        //手动开启线程
        //[thread start];
        //给线程取名字
        //thread.name=@"SonThread";
        
        /*用类方法创建一个子线程,执行[self needLongTimeFuction];
         第一个参数:执行的方法
         第二个参数:谁去执行
         第三个参数:执行这个需要传递的参数
         特点:会自动开启线程
         */
        [NSThread detachNewThreadSelector:@selector(needLongTimeFuction) toTarget:self withObject:nil];
        
    }
    
    if (button.tag == 101) {
        NSLog(@"不卡了!!!");
    }
}

#pragma mark - 耗时操作
-(void)needLongTimeFuction{
    
    //注意: 子线程最好放在自动释放池中
    @autoreleasepool {
        NSLog(@"%@", [NSThread currentThread]);
        NSLog(@"耗时操作执行开始!!!");
        //当前线程休眠多长时间,例如模拟请求网络数据
        [NSThread sleepForTimeInterval:60.0];
        NSLog(@"耗时操作执行结束!!!");
        
        
        //耗时操作完成,如果需要刷新UI,必须要在主线程里刷新页面
        //[self reloadCurrentPageUI];
        
        [self performSelectorOnMainThread:@selector(reloadCurrentPageUI) withObject:nil waitUntilDone:YES];
        
        //当前线程休眠多长时间
        //[NSThread sleepForTimeInterval:10.0];
        
        //返回B时间过去A秒之后的时间 [dateWithTimeInterval:A sinceDate:B]
        //NSDate *date=[NSDate dateWithTimeInterval:10 sinceDate:[NSDate date]];
        //当前线程休眠到某个时间
        //[NSThread sleepUntilDate:date];
        
        //退出当前线程
        //[NSThread exit];
    }
}

#pragma mark - 刷新界面UI
-(void)reloadCurrentPageUI{
    NSLog(@"UI刷新成功!!!");
}

@end
上一篇下一篇

猜你喜欢

热点阅读