gpt4 book ai didi

ios - Grand Central 调度和功能

转载 作者:行者123 更新时间:2023-11-29 03:17:48 27 4
gpt4 key购买 nike

我一直在看this question尝试解决我的问题 here . tl;dr 是我想使用 GCD 让我在执行某些任务时显示“等待”屏幕,然后在完成后隐藏屏幕。现在,我有

- (void) doStuff
{
// Show wait on start
[self.waitScreen setHidden:NO];

dispatch_queue_t queue = dispatch_queue_create("com.myDomain.myApp",null);
dispatch_async(queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
// Double nesting the dispatches seems to allow me to do UI changes as part of 'Code to execute' below.
// If I do not double nest like this, the UI still freezes while it executes
dispatch_queue_t queue2 = dispatch_queue_create("com.myDomain.myApp",null);
dispatch_async(queue2, ^{
dispatch_async(dispatch_get_main_queue(), ^{

// Code to execute
{
//... Do my time consuming stuff here ...
// For testing purposes, I'm using
int i = 0;
while (i < 1000000000)
{
i++;
}
}

// Hide Wait Screen on End
[self.waitScreen setHidden:YES];
});
});
});
});
}

这正是我想要的。我正在调用 [self doStuff]

- (IBAction) buttonTouchUpInside:(id)sender
{
[self doStuff];
}

- (void) doStuff
{
// ... code from first code block here ...
}

到目前为止,一切都完美无缺。现在,我发现我需要在函数调用中使用它。所以我需要这样的东西:

- (IBAction) buttonTouchUpInside:(id)sender
{
NSMutableString *string= [self doStuff];

// ... use 'string' to do other stuff ...
// For testing, I'm using
self.label.text = string;
}

- (NSMutableString *) doStuff
{
// ... code from first code block here ...
}

我需要如何更改语法才能使用 dispatch_async 传递变量?


我查看了 Apple Docs并尝试过

- (IBAction) buttonTouchUpInside:(id)sender
{
NSMutableString *string= [self doStuff];

// ... use 'string' to do other stuff - shows 'nil' when I put breakpoints here ...
// For testing, I'm using
self.label.text = string;
}

- (NSMutableString *) doStuff
{
__block NSMutableString *string = [[NSMutableString alloc] initWithString:@"Initing"];

// Show wait on start
[self.waitScreen setHidden:NO];

dispatch_queue_t queue = dispatch_queue_create("com.myDomain.myApp",null);
dispatch_async(queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_queue_t queue = dispatch_queue_create("com.myDomain.myApp",null);
dispatch_async(queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{

// Code to execute
{
int i = 0;
while (i < 1000000000)
{
i++;
}

[string setString:@"Hello World"];
}

// Hide Wait Screen on End
[self.waitScreen setHidden:YES];
});
});
});
});

return string;
}

但是当我运行它时,label 只显示 Initing。我需要它来显示 Hello World。我在 block 中所做的任何更改都没有通过。

在查看了其他一些问题后,这似乎被称为“竞争条件”。据我了解,一旦它命中 dispatch_async, block 中的代码开始在新线程上运行,但 block 外的代码继续同时在旧线程上运行。所以看起来 block 外的线程在运行 block 的线程可以到达 [string setString:@"Hello World"];self.label.text = string 之前。如何让 self.label.text = string 行等到 [string setString:@"Hello World"]; 完成?

最佳答案

首先,您对双重嵌套的推理是有缺陷的。不确定它为什么会起作用,但正确的方法是做一些异步工作,并且任何时候你想更新 ui 时,将该代码包装在主队列的一个 block 中。

- (void) doStuff
{
// Show wait on start
[self.waitScreen setHidden:NO];

// queue should be a global variable, you don't want to create it every time you
// execute doStuff
dispatch_async(queue, ^{
// Code to execute
{
//... Do my time consuming stuff here ...
// For testing purposes, I'm using
int i = 0;
while (i < 1000000000)
{
i++;
}
}

dispatch_async(dispatch_get_main_queue(), ^{
// Hide Wait Screen on End
[self.waitScreen setHidden:YES];
});
});
}

由于您的队列是异步执行工作的,因此您不能不等待就简单地从 doStuff 返回一个值,这将阻塞您再次调用 doStuff 的队列。

如果您只想在标签上设置一个值,也可以在主队列上执行的 block 中执行此操作,例如隐藏等待屏幕。

另一种常见的处理方法是提供一个回调 block ,以便在工作完成后立即执行。

- (void) doStuffWithCompletionBlock:(void(^)(NSString *))block
{
// again, a global variable for the queue
dispatch_async(queue, ^{
// do some work here that shouldn't block the UI

dispatch_async(dispatch_get_main_queue(), ^{
block(@"My result string");
});
});
}

- (void) myAction:(id)sender
{
__weak typeof(self) weakSelf = self;
[self doStuffWithCompletionBlock:^(NSString *result) {
weakSelf.label.text = result;
}];
}

请注意,我在主队列上调用了完成 block ,这是一个选择。您可以忽略这一点,但您仍然需要稍后在完成 block 本身中对主队列进行所有 UI 更新。

关于ios - Grand Central 调度和功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21465757/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com