Apple建议使用静态全局或__block存储类型修改外部变量。
dispatch_async()需要一个没有参数的块。
从该块中修改self.prop最干净最安全的方法是什么?
使用原子设定器?
将块包裹在块中?
发回主线程?
我的情景: 该块正在发出网络请求。 当它完成后,我必须解析一些返回的数据并在几个不同的对象上设置属性,以便我可以跟进网络请求。 正在处理块异步,但根据用户输入,可以使用第一个块所需的数据将第二个块提交给队列。 这就是我想做的事。
@implementation MyNetworkManager {
dispatch_queue_t op_queue;
NSURL *_redirectedURL;
}
void (^initPageOperation) (void) = ^(void) {
NSURL *url;
NSMutableURLRequest *urlRequest;
url = [NSURL URLWithString:domain];
urlRequest =
[NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:5];
[urlRequest setHTTPMethod:@"GET"];
NSData *data = nil;
NSURLResponse *urlResponse = nil;
NSError *err = nil;
data = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&urlResponse
error:&err];
if (urlResponse) {
if (![urlResponse.URL isEqual:url]) {
//Here's where I want to set the redirectedURL.
_redirectedURL = urlResponse.URL;
}
}
};
答案 0 :(得分:2)
Apple建议与修改变量的内容有关。如果您正在修改引用的对象(在您的情况下为self.prop
),那么无论是否使用GCD,问题都是相同的 - 您如何编写属性/方法以便它线程安全吗?
有多个答案(@synchronized { }
,dispatch_semaphore_X()
,NSLock
,...),确保线程安全并找到符合您需求的研究。
答案 1 :(得分:1)
你说:
Apple建议使用静态全局或
__block
存储类型修改外部变量。
我不确定我会这么说。我认为更合乎逻辑的思考方式是“如果你想修改方法的局部变量,你可以在该变量的声明中使用__block
限定符,但不需要该限定符”。简而言之,类实例变量(或属性),__block
变量,全局变量等不需要static
限定符。
你继续说:
dispatch_async()需要一个没有参数的块。
当然,那是真的。但是,再次,如果您正在编写自己的完成块,则可以将它们定义为具有参数。或者您可以使用具有自己的完成块类型的API调用及其自己的参数。例如:
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// here you can initiate the parse of the data,
// capturing the url from the response, or examining
// the error
}];
completionHandler
是一个带参数的块。
所以,是的,一个简单的dispatch_async
(或NSOperationQueue
等价物,addOperationWithBlock
)不带参数,当你开始编写自己的完成块时,你会经常写带参数的那些。
从该区块内修改
self.prop
最干净最安全的方法是什么?
从技术上讲,你可以修改它。但是,诀窍在于,如果您有多个线程同时可以访问它,那么您可以通过locking mechanisms中的一个来同步与该类属性的交互,或者您可以eliminate that locking code by performing all interaction with that class property with a serial queue(串行)您创建的队列或主队列。)
使用原子设定器?
仅适用于simple data types。但是,在处理对象时,原子设置器并不会给你带来太大的影响。您需要一些其他机制来同步与变量的交互,例如上面描述的那些。
将块包裹在块中?
排序,但技术上并不是将它包装在提供线程安全性的块中,而是将该块分派给一个串行队列(并确保与该属性的所有其他交互都在同一个串行队列上完成)。
发回主线程?
在某些简单的情况下,是的,那也可以完成这项工作。但请确保您没有向主线程发送任何非常耗时的内容,否则您的UI可能会受到影响(或更糟)。
我有一个假设的情景。一般来说,我试图了解块的最佳实践。
有许多不同的模式,一个假设的问题很难回答,因为细节完全取决于业务需求的确切含义。为了获得最佳实践,我建议您观看引用的WWDC视频Rob Mayoff Asynchronous Design Patterns with Blocks, GCD, and XPC。您还可以看到WWDC 2012 Building Concurrent User Interfaces on iOS。这些也基于早期视频的概念,例如WWDC 2011视频,例如Blocks and Grand Central Dispatch in Practice和Mastering Grand Central Dispatch。