Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 使iOS块同步执行_Iphone_Ios_Cocoa Touch_Ios4_Objective C Blocks - Fatal编程技术网

Iphone 使iOS块同步执行

Iphone 使iOS块同步执行,iphone,ios,cocoa-touch,ios4,objective-c-blocks,Iphone,Ios,Cocoa Touch,Ios4,Objective C Blocks,如何使块同步执行,或使函数在返回语句之前等待处理程序,以便从块传回数据 -(id)performRequest:(id)args { __block NSData *data = nil; [xyzclass requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) { data = [NSData dataWithData:r

如何使块同步执行,或使函数在返回语句之前等待处理程序,以便从块传回数据

-(id)performRequest:(id)args
{
__block NSData *data = nil;   

    [xyzclass requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
        data = [NSData dataWithData:responseData];
    }];

    return data;
}

您可以在另一个线程中执行同步请求,如下面的代码所示

-(void)performRequest:(id)args
{

 NSURLResponse *response = nil;
 NSError *error = nil;
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
 data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
}
在主线程中,您可以称之为

[self performSelectorInBackground:@selector(performRequest:) withObject:args];
或者,您可以使用以下方法执行异步请求

[NSURLConnection alloc]initWithRequest:request delegate:self];

并为NSURLConnection实现委托方法

是否确实要同步执行? 如果是,则可以在块中调用(或放置)处理程序函数,或者在处理程序完成并希望返回值时使用Jignesh advice(和“performSelectorInMainThread”)

异步方式(稍微)困难,但更好: -它迫使您编写干净的代码(不传递方便的变量) -你可以执行其他操作,这样用户就不会等着认为你的应用程序太慢了

你真的应该给它两到三个小时的时间去实现异步。小小的痛苦换来完全的收获。
您还可以查看键值观察。

您可以这样做

-(id)performRequest:(id)args
{
__block NSData *data = nil;   

 [xyzclass performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse          *urlResponse, NSError *error) {

     dispatch_sync( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{

     data = [NSData dataWithData:responseData];

     });

 }];

return data;
}

您可以添加一个处理返回数据的方法,并在块中调用该方法:

-(void)performRequest:(id)args{
    __block NSData *data = nil;   

    [xyzclass requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
        data = [NSData dataWithData:responseData];
        [self processData:data]; //method does something with the data 
    }];
}

异步几乎总是更好。但如果您想要同步:

-(id)performRequest:(id)args
{
__block NSData *data = nil;   

    [xyzclass requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
        data = [NSData dataWithData:responseData];
    }];

    while(!data) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
    return data;
}

免责声明: CocoaCouchDeveloper说,当然,只有当完成块和运行循环在同一个线程上时,这才会起作用。 我认为,因为我所知道的许多(大多数)完成处理程序都是这样工作的,但其中大多数在原则上是有效的

以上内容不是线程安全的
使用信号灯或其他可能的东西。

我还说我不提倡这个

在这种情况下你可以使用信号量

-(id)performRequest:(id)args
{
    __block NSData *data = nil;   
     dispatch_semaphore_t sem = dispatch_semaphore_create(0);
     [xyzclass requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
       data = [NSData dataWithData:responseData];
       dispatch_semaphore_signal(sem);
     }];
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    return data;
}

信号量将阻止进一步语句的执行,直到收到信号为止,这将确保您的函数不会过早返回。

如果我需要访问一个除了使用块之外别无选择的类,例如:[classxyz requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL-grated,n错误*错误){}];别无选择,如果我错了请纠正我您可以实现委托方法正如我在回答中所说的,控制将进入ConnectionIDFinishLoading:在请求成功完成时,如果您从服务器请求编辑以生成更具体的代码段,在任何时候如果您遇到需要进行异步同步,则有一些你的设计有很大的错误。只是好奇,你为什么要这样做?如果你只是想完成这一块,那么你的“性能要求”在哪里方法还应该包括一个应该在内部块完成内部调用的块。正如Kunal指出的,您的设计有一些问题,因为您希望这样做。我希望看到一个很好的简单教程来理解这一点,因为到目前为止,教程太基本,没有用,例如Practical studio的乘法器示例,或者太简单晦涩是有用的。你知道吗?在调用处理程序之前,
return
语句中没有出现这种情况吗?免责声明:内联编写。[可能不是100%,但清楚地显示了你必须做的事情]你能保证对变量数据的访问是线程安全的并且涉及内存障碍吗?我怀疑是这样。如果没有内存障碍,编译器有资格将数据保存在寄存器中,因此,数据在调用线程中永远不会更新。实际上,只有当完成处理程序在运行循环被执行。我刚刚做了一个简化的测试,结果是:数据变量将保存在一个寄存器中,该寄存器永远不会更新(while循环永远不会返回)。也没有内存障碍,这意味着,如果要更新数据,对数据的访问不能保证是原子/安全的,返回的指针值可能会被破坏。但是:Objective-C将阻止编译器使用许多优化机会,并增加它仍然工作的机会;)OP的问题很一般。我们永远不应该假设在主线程上执行一个完成处理程序,除非它被显式地记录下来。事实上,在一个“已知的”线程上执行一个处理程序线程是一种不好的做法,因为它增加了死锁的可能性。在一些例外情况下,在主线程上执行处理程序是有意义的:例如UIViews动画。AFN不属于此组,很难-即使它使用主线程。相比之下,在AVFoundation中,处理程序将使用私有线程(请参阅“与AV基金会并行编程”)。这是正确的答案,假设您没有在主线程上执行。此方法仅适用于在单独线程(而不是调用线程)上运行和调用完成的异步方法。注意:如果您在主线程上,您仍然可以使用信号量,只需稍微修改它,请参见此处: