Objective c 使用GCD修改对象/外部变量的最干净、最安全的方法
Apple建议使用静态全局或_块存储类型修改外部变量 dispatch_async()需要不带参数的块 从该块中修改self.prop最干净、最安全的方法是什么 使用原子设置器 把这个街区围成一个街区 调度回主线程 我的设想: 该块正在发出网络请求。 当它完成后,我必须解析一些返回的数据,并在几个不同的对象上设置属性,以便我可以发出后续的网络请求。 这些块正在异步处理,但根据用户输入,第二个块可以提交到队列,其中包含第一个块所需的数据。 这是我想做的Objective c 使用GCD修改对象/外部变量的最干净、最安全的方法,objective-c,grand-central-dispatch,Objective C,Grand Central Dispatch,Apple建议使用静态全局或_块存储类型修改外部变量 dispatch_async()需要不带参数的块 从该块中修改self.prop最干净、最安全的方法是什么 使用原子设置器 把这个街区围成一个街区 调度回主线程 我的设想: 该块正在发出网络请求。 当它完成后,我必须解析一些返回的数据,并在几个不同的对象上设置属性,以便我可以发出后续的网络请求。 这些块正在异步处理,但根据用户输入,第二个块可以提交到队列,其中包含第一个块所需的数据。 这是我想做的 @implementation MyNetw
@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;
}
}
};
Apple建议修改变量的内容。如果改为修改变量引用的对象(
self.prop
,在您的情况下),那么问题在使用或不使用GCD的情况下都是一样的-如何编写属性/方法以使其线程安全
对此有多种答案(
@synchronized{}
,dispatch\u semaphore\u X()
,NSLock
,…),研究确保线程安全并找到满足您需求的方法。苹果的建议与修改变量内容有关。如果改为修改变量引用的对象(self.prop
,在您的情况下),那么问题在使用或不使用GCD的情况下都是一样的-如何编写属性/方法以使其线程安全
对此有多种答案(@synchronized{}
,dispatch\u semaphore\u X()
,NSLock
,…),研究确保线程安全并找到满足您需要的方法。您说过:
Apple建议使用静态全局或\u块
存储类型修改外部变量
我不确定我是否会这样说。我认为更合乎逻辑的思考方式是“如果您想修改一个方法的局部变量,您可以在该变量的声明上使用\u块
限定符,否则就不需要该限定符”。简而言之,类实例变量(或属性)、静态变量、全局变量等不需要\u块
限定符
你接着说:
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\u async
(或NSOperationQueue
等价物,addOperationWithBlock
)不带参数,当您开始编写自己的完成块时,您通常会编写带参数的块
从该块中修改self.prop
最干净、最安全的方法是什么
从技术上讲,您可以修改它。不过,诀窍是,如果您有多个线程可能同时访问该类,那么您可以通过或(您创建的串行队列或主队列)之一将您的交互与该类属性同步
使用原子设置器
这只适用于。不过,在处理对象时,atomic setter不会给您带来太多好处。您需要一些其他机制来同步与变量的交互,如上面所述
把这个街区围成一个街区
某种程度上,但从技术上讲,并不是将其包装在一个块中以提供线程安全,而是将该块分配到一个串行队列(并确保与该属性的所有其他交互都在同一个串行队列上完成)
调度回主线程
在某些简单的情况下,是的,这也可以完成工作。但是,请确保您没有将任何非常耗时的任务分派到主线程,否则您的UI可能会受到影响(或更糟)
我有一个假设情景。总的来说,我正在努力理解块的最佳实践
有这么多不同的模式,一个假设性的问题很难回答,因为细节完全不同,具体取决于业务需求。为了获得最佳实践,我鼓励您观看WWDC视频Rob Mayoff。您还可以查看WWDC 2012。这些概念也建立在早期视频的基础上,如WWDC 2011视频,如和。您说过:
Apple建议使用静态全局或\u块
存储类型修改外部变量
我不确定我是否会这样说。我认为更合乎逻辑的思考方式是“如果您想修改一个方法的局部变量,您可以在该变量的声明上使用\u块
限定符,否则就不需要该限定符”。简而言之,类实例变量(或属性)、静态变量、全局变量等不需要\u块
限定符
你接着说:
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\u async
(或NSOperationQueue
等价物,addOperationWithBlock
)不带参数,当您开始编写自己的完成块时,您通常会编写带参数的块
修改self.prop最干净最安全的方法是什么