使用iOS上的Grand Central Dispatch,如果常规Objective-C块不在调度队列中,它们运行在哪个队列(如果有)上?
下面的选项#1是否运行某种隐含队列?它似乎没有在主队列上运行,因为当我尝试更新那里的UI内容时,它一直抱怨,直到我移动到选项#3,所以我假设块有自己的队列或线程?在它抱怨之前,我的印象是,如果我不启动调度队列,事情就会像正常一样运行,在我看来,这将是在主队列上。下面是一些示例代码来说明:使用iOS上的Grand Central Dispatch,如果常规Objective-C块不在调度队列中,它们运行在哪个队列(如果有)上?,ios,objective-c,multithreading,objective-c-blocks,grand-central-dispatch,Ios,Objective C,Multithreading,Objective C Blocks,Grand Central Dispatch,下面的选项#1是否运行某种隐含队列?它似乎没有在主队列上运行,因为当我尝试更新那里的UI内容时,它一直抱怨,直到我移动到选项#3,所以我假设块有自己的队列或线程?在它抱怨之前,我的印象是,如果我不启动调度队列,事情就会像正常一样运行,在我看来,这将是在主队列上。下面是一些示例代码来说明: // UserViewController.h @interface UserViewController : NSObject @property(nonatomic, strong) Server *ser
// UserViewController.h
@interface UserViewController : NSObject
@property(nonatomic, strong) Server *server;
@property(nonatomic, strong) User *user;
@end
// UserViewController.m - Controller that sets a block for use in another class
@implementation UserViewController
- (void)doSomething {
// I'd like to call other methods and set @properties from the controller and I've heard
// __weak is the correct keyword to use (rather than __block or __strong).
__weak UserViewController *weakController = self;
// Option #0 - Outside of block
weakController.user = [[RHZUser alloc] init];
server.callbackBlock = ^(NSURLResponse *response, NSData *data, NSError *error) {
// Option #1 - Outside of dispatch queues. Is this in some sort of default queue?
weakController.user = [[RHZUser alloc] init];
dispatch_queue_t backgroundQueue
= dispatch_queue_create("com.example.backgroundQueue", nil);
dispatch_async(backgroundQueue, ^{
// Option #2 - This is on the serial queue I created
weakController.user = [[RHZUser alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
// Option #3 - The main queue where all my UI is
weakController.user = [[RHZUser alloc] init];
} // dispatch_async
} // dispatch_async
}; // self.callbackBlock
}
@end
// Server.m - Class that uses the block defined in the controller
@implementation Server
- makeAServerCall {
[NSURLConnection sendAsynchronousRequest:
[NSMutableURLRequest requestWithURL:restServiceURL]
queue:[[NSOperationQueue alloc] init]
completionHandler:self.callbackBlock];
}
@end
可能是
Server
错误地(在我看来)在非主队列的队列上实现了回调块。您可以通过检查[NSThread isMainThread]来检查选项#1是否绝对不在主队列上代码>。通常只更改主线程上的UIKit
元素(也有一些例外-一如既往!)
通常,web服务回调(或完成)块被发送回主线程,例如。块是一段代码,执行时在特定队列上运行。在某个对象上设置块不会使其运行,也不会附加到某个特定队列
在选项1的情况下,可以在服务器的实例上设置块特性。这并不意味着它已运行,它所做的只是让任何有权访问该块的人都可以访问该代码。因为属性的名称是callbackBlock
,所以我假设Server
实例在完成某项任务时执行块
这是当块绑定到队列时Server
的实现决定它是否在主队列上运行,并且应该记录(可能在its.h中)它是否在主队列上运行。如果它没有文档记录,但我绝对需要它在主队列上运行,那么我总是安全地运行它,并通过将它包装在dispatch\u async
中来确保它在主线程上被调用
编辑:
假设您的服务器
实现与服务器
相同,您可以使用alloc/init创建一个新队列,并将其传递给NSURLConnection
。从NSURLConnection
文档中:
排队
请求完成或失败时处理程序块被调度到的操作队列
因此,行为确实是有文档记录的,如果您希望在主队列上调用处理程序,只需传递dispatch\u get\u main\u queue
,就可以调用一个块。与使用函数指针的调用相同;实际上与使用函数指针的语法相同。该块将与调用方在同一线程上运行
dispatch_block_t myBlock = ^ { NSLog (@"This is a block!"); };
myBlock ();
在运行代码的同一线程上打印“thisablock!”。回调将在调用它们的任何线程上运行。因此,您的“选项1”块将在该块的调用者决定对其执行的任何队列上执行。通常,这应该通过使用回调的方法来记录。有一些使用回调的方法允许您传入队列,它们将在该队列上调度回调 块就是可以像函数一样调用的东西。他们不关心线程和队列本身,也不做任何事情。如果您问“在iOS上使用Grand Central Dispatch,如果常规C函数不在调度队列中,它们运行在什么队列(如果有的话)”或“在iOS上使用Grand Central Dispatch,如果常规Objective-C方法不在调度队列中,它们运行在什么队列(如果有的话)”时,您的问题将完全相同答案就是这个问题的标题
那么这些问题的答案是什么?嗯,函数(或方法或块)在调用时运行。就这么简单。所以根据定义,它在调用它时所处的任何线程或队列上运行。因此,块中的代码在哪个线程中运行取决于调用它的代码在哪个线程中。那么这个街区叫什么名字?该块被传递到+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]代码>,正是这段代码以某种方式调用了它。我们没有该库的代码,但是它的文档表明完成处理程序在作为第二个参数传入的NSOperationQueue
中执行。将新的NSOperationQueue
对象作为第二个参数传递
NSOperationQueue
维护运行操作的内部线程或调度队列。您无权访问并且不应关心此内部队列;您只知道这些操作是在与其他队列和线程分离的对象上执行的,因此肯定不是主线程。这是被否决的特定原因吗?我很想知道为什么-我错过了或得到了一些不正确的东西吗?谢谢,我会尝试把代码放进去,看看它是否在主线程上。(P.S.反对票不是我投的。)@Tendiousjay是的,我不认为是你。。。!总是这样-你已经找到了解决问题的方法,但只是想知道为什么会发生这样的事情,所以我的答案不仅仅是一个解决方案,而是一句话p这里有doSomething
从?K调用,我检查过了。选项#0和#3对于[NSThread isMainThread]是真的。因此选项#1(块中的代码)肯定运行在不同的线程上,但不确定它是否在某种默认队列中。(注意:选项#0最初不在我的问题中,为了清楚起见,我更新了我的答案以包含它。)哈,我在分配/初始化传递给NSURLConnection的NSOperationQueue的地方完全隔开(花了太多时间盯着UserViewController.m)。选项#1在传递给NSURLConnection的任何队列上运行完全有意义。我不确定我是否需要它在dispatch\u get\u main\u队列上运行,但建议使用+1。(newacct还提到了NSO操作