0
点赞
收藏
分享

微信扫一扫

c# 中List的介绍说明

小飞侠熙熙 2024-11-03 阅读 20

在iOS 里面,项目打开就会运行一个主线程,所有的UI都在主线程里进行.其他网络请求或者耗时操作理论上也可以在主线程运行,但是如果太耗时,那么就会影响主线程其他UI.所以需要开字线程来进行耗时操作,子线程进行完耗时操作之后,如果项目需求有需要刷新UI,或者改变UI,一定得回到主线程进行修改/刷新.

下面介绍三种iOS里线程模式

前情提要:在View上创建一个UILabel, 点击屏幕空白处开启一个子线程,在子线程里模拟耗时操作,耗时操作完毕后需要改变UILabel上的文字.

- (void)viewDidLoad 
{
    [super viewDidLoad];
 
    self.markLabel = [[UILabel alloc]initWithFrame:CGRectMake(50, 200, 300, 40)];
    self.markLabel.backgroundColor = [UIColor greenColor];
    self.markLabel.textAlignment = NSTextAlignmentCenter;
    self.markLabel.text = @"子线程开启之前的String";
    [self.view addSubview:self.markLabel];
}

1.NSThread

1.1. 点击空白页面,开启线程(先模拟不在主线程刷新UI的错误写法)

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //模拟线程耗时操作,并在耗时操作后改变label的String
    
    [self threadModel];
}


- (void)threadModel
{
    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(threadUpdateUI) object:nil];
    [thread start];
}

- (void)threadUpdateUI
{
    //模拟耗时操作
    [NSThread sleepForTimeInterval:2];

     //耗时操作后直接刷新UI (这是模拟错误的方法)
     self.markLabel.text = @"修改后的Sting"; 
}

按照以上的写法,直接报错,报错提示如下图所示: 

must be used from main thread only : 一定且只有从主线程刷新

因此可知,需要进入主线程去刷新,那么NSTread模式怎么进入主线程呢? 看下面的代码

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //模拟线程耗时操作,并在耗时操作后改变label的String
    
    [self threadModel];
}

- (void)threadModel
{
    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(threadUpdateUI) object:nil];
    [thread start];
}

- (void)threadUpdateUI
{
    //模拟耗时操作
    [NSThread sleepForTimeInterval:2];
    //NSThread 找到主线程
    [self performSelectorOnMainThread:@selector(uodateMainUI) withObject:nil waitUntilDone:NO];
    
}

- (void)uodateMainUI
{
    self.markLabel.text = @"修改后的Sting";
}

以上是NSThread 找到主线程,并且刷新UI的方法.

接下来介绍CGD和NSOperation 找到主线程的方法

2.CGD

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //模拟线程耗时操作,并在耗时操作后改变label的String
    
    [self CGDModel];
}

- (void)CGDModel
{
    //队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    /*
     我这里使用global_queue来模拟,你也可以使用并发队列/串行队列模拟
     dispatch_queue_t queue = dispatch_queue_create(@"并发队列", DISPATCH_QUEUE_CONCURRENT);
     dispatch_queue_t queue = dispatch_queue_create(@"串行队列", DISPATCH_QUEUE_SERIAL);
     但是不能用主队列来模拟,因为主队列本身就有主线程
     */
    
    //任务
    dispatch_async(queue, ^{
        
        //模拟耗时操作
        [NSThread sleepForTimeInterval:2];
        
        //CGD模式回到主线程,因为CGD和NSOperation只有任务和队列的概念,所以主队列就是主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            self.markLabel.text = @"修改后的Sting";
        });
        
    });
}

3.NSOperation

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //模拟线程耗时操作,并在耗时操作后改变label的String
    [self operationModel];
}

- (void)operationModel
{
    //队列
    NSOperationQueue * queue = [[NSOperationQueue alloc]init];
    //任务
    [queue addOperationWithBlock:^{
        
        //模拟耗时操作
        [NSThread sleepForTimeInterval:2];
        
        //找到主队列(NSOperation只有任务和队列的概念,所以主队列就是主线程)
        [NSOperationQueue.mainQueue addOperationWithBlock:^{
                 
            self.markLabel.text = @"修改后的Sting";
        }];
    
    }];
}
举报

相关推荐

0 条评论