我在我的应用中使用GCDAsyncSocket
(CocoaAsyncSocket
)进行套接字通信。由于GCDAsyncSocket
的异步性质,我的网络请求(下面的submitMessage
)与收到数据时运行的回调块(socket:didReadData
)分离。
- (void)submitMessage:(NSDictionary *)messageObject onCompletion:(completionBlock)block {
...
[_socket writeData:requestData withTimeout:self.timeout tag:0];
[_socket readDataToLength:4 withTimeout:self.timeout tag:TAG_HEADER];
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
...
NSDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
if (self.completionBlock != nil)
self.completionBlock(responseObject);
}
}
这种方法适用于一次性交易。但在某些情况下,我需要发布请求,然后使用收到的数据,发布另一个请求。我不能让它正常工作。基本上,我需要这样的东西:
[self submitMessage:request1 onCompletion:^(NSDictionary *response1) {
(...callback 1...)
}];
[self submitMessage:request2 onCompletion:^(NSDictionary *response2) {
(...callback 2...)
}];
}];
或
[self submitMessage:request1 onCompletion:^(NSDictionary *response1) {
(...callback 1...)
}];
[self submitMessage:request2 onCompletion:^(NSDictionary *response2) {
(...callback 2...)
}];
其中订单是严格的request1 - callback1 - request2 - callback2。
所以问题是,如何在第一个请求回调后阻止第二个请求运行? GCD
(dispatch_sync
?)会成为可行的方法吗?
修改
我最终使用类似于@tigloo建议的解决方案(因此接受他的回答),但使用NSCondition
代替GCD
(如果有人对细节感兴趣,我跟着this great discussion )。我已经在运行多个线程(主要的UI,另一个线程中的高级套接字通信,以及第三个线程中的套接字操作)。设置一个类属性并使用NSCondition
锁定GCDAsyncSocket
委托直到响应到达似乎是最干净的方法。
答案 0 :(得分:2)
我想你差不多了。
怎么样?[self submitMessage:request1 onCompletion:^(NSDictionary *response1) {
// here, do something with response1 and create request2...
// then you can make request2 directly at the end of the callback:
[self submitMessage:request2 onCompletion:^(NSDictionary *response2) {
// here, do something with response2...
}];
}];
不需要GCD指令,不需要阻止执行(无论如何这都是一种不好的做法)。这会解决您的问题吗?
答案 1 :(得分:1)
最简单的方法是将您的请求附加到串行调度队列,然后使用dispatch_sync()等待它们完成。 A discussion on StackOverflow can be found here
实施它的实际方式取决于您的偏好。可能的想法如下:
通过这种方式,您可以构建多个SyncRequest实例,每个实例都处理一个同步请求。粗略草图实现:
@interface SyncRequest
@property bool requestFinished;
@end
@implementation SyncRequest
dispatch_queue_t syncRequestQueue;
-(id)init
{
self = [super init];
if ( !self )
return nil;
self.requestFinished = NO;
syncRequestQueue = dispatch_queue_create("com.yourid.syncrequest", DISPATCH_QUEUE_SERIAL);
return self;
}
-(void) sendSyncRequest:(NSDictionary*)messageObject
{
// submit message here and set requestFinished = YES in completion block
// wait for completion here
dispatch_sync(syncRequestQueue, ^(void){while(!self.requestFinished);});
}
@end
注意:我编写的代码没有编译器,您可能必须在dispatch_sync调用中创建对“self”的间接引用,以避免循环引用。