我的应用就是这样工作的: - 制作相册并拍照 - 将它们发送到我的服务器上 - 图片分析后得到答案/补充信息。
发送部分有问题。这是代码
@interface SyncAgent : NSObject <SyncTaskDelegate>
@property NSOperationQueue* _queue;
-(void)launchTasks;
@end
@implementation SyncAgent
@synthesize _queue;
- (id)init
{
self = [super init];
if (self) {
self._queue = [[NSOperationQueue alloc] init];
[self._queue setMaxConcurrentOperationCount:1];
}
return self;
}
-(void) launchTasks {
NSMutableArray *tasks = [DataBase getPendingTasks];
for(Task *t in tasks) {
[self._queue addOperation:[[SyncTask alloc] initWithTask:t]];
}
}
@end
和SyncTask:
@interface SyncTask : NSOperation
@property (strong, atomic) Task *_task;
-(id)initWithTask:(Task *)task;
-(void)mainNewID;
-(void)mainUploadNextPhoto:(NSNumber*)photoSetID;
@end
@implementation SyncTask
@synthesize _task;
-(id)initWithTask:(Task *)task {
if(self = [super init]) {
self._task = task;
}
return self;
}
-(void)main {
NSLog(@"Starting task : %@", [self._task description]);
// checking if everything is ready, sending delegates a message etc
[self mainNewID];
}
-(void)mainNewID {
__block SyncTask *safeSelf = self;
[[WebAPI sharedClient] createNewPhotoSet withErrorBlock:^{
NSLog(@"PhotoSet creation : error")
} andSuccessBlock:^(NSNumber *photoSetID) {
NSLog(@"Photoset creation : id is %d", [photoSetID intValue]);
[safeSelf mainUploadNextPhoto:photoSetID];
}];
}
-(void)mainUploadNextPhoto:(NSNumber*) photoSetID {
//just admit we have it. won't explain here how it's done
NSString *photoPath;
__block SyncTask *safeSelf = self;
[[WebAPI sharedClient] uploadToPhotosetID:photoSetID withPhotoPath:photoPath andErrorBlock:^(NSString *photoPath) {
NSLog(@"Photo upload error : %@", photoPath);
} andSuccessBlock:^(NSString *photoPath) {
NSLog(@"Photo upload ok : %@", photoPath);
//then we delete the file
[safeSelf mainUploadNextPhoto:photoSetID];
}];
}
@end
每个网络操作都是以这种方式使用AFNetworking完成的:
-(void)myDummyDownload:(void (^)(NSData * data))successBlock
{
AFHTTPClient* _httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.google.com/"]];
[_httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
NSMutableURLRequest *request = [_httpClient requestWithMethod:@"GET" path:@"/" nil];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
AFHTTPRequestOperation *operation = [_httpClient HTTPRequestOperationWithRequest:(NSURLRequest *)request
success:^(AFHTTPRequestOperation *operation, id data) {
if(dataBlock)
dataBlock(data);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Cannot download : %@", error);
}];
[operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
NSLog(@"Request time out");
}];
[_httpClient enqueueHTTPRequestOperation:operation];
}
我的问题是:我的连接是异步进行的,因此即使[self._queue setMaxConcurrentOperationCount:1]
中有SyncAgent
,每个任务都会一起启动而无需等待上一个任务完成。
我是否需要同步执行每个连接?我不认为这是一个好主意,因为连接永远不应该以这种方式完成,也因为我可能在其他地方使用这些方法并且需要它们在后台执行,但我找不到更好的方法。有什么想法吗?
哦,如果我的代码中有任何错误/拼写错误,我可以向你保证,当我在粘贴之前尝试对其进行总结时,它现在正在运行中没有任何问题。
谢谢!
PS:很抱歉,我找不到更好的解释问题的方法。
编辑:我发现使用信号量更容易设置和理解:How do I wait for an asynchronously dispatched block to finish?
答案 0 :(得分:2)
如果您对服务器有任何控制权,那么您应该考虑创建一个API,允许您以任意顺序上传照片,以便支持多个同时上传(对于大批量来说,这可能会快得多) )。
但是如果你必须做同步的事情,最简单的方法可能是在请求的完成块中排队新的请求。即。
// If [operations length] == 1, just enqueue it and skip all of this
NSEnumerator *enumerator = [operations reverseObjectEnumerator];
AFHTTPRequestOperation *currentOperation = nil;
AFHTTPRequestOperation *nextOperation = [enumerator nextObject];
while (nextOperation != nil && (currentOperation = [enumerator nextObject])) {
currentOperation.completionBlock = ^{
[client enqueueHTTPRequestOperation:nextOperation];
}
nextOperation = currentOperation;
}
[client enqueueHTTPRequestOperation:currentOperation];
答案 1 :(得分:1)
以下代码适用于我,但我不确定其缺点。拿一小撮盐。
- (void) main {
NSCondition* condition = [[NSCondition alloc] init];
__block bool hasData = false;
[condition lock];
[[WebAPI sharedClient] postPath:@"url"
parameters:queryParams
success:^(AFHTTPRequestOperation *operation, id JSON) {
//success code
[condition lock];
hasData = true;
[condition signal];
[condition unlock];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure code
[condition lock];
hasData = true;
[condition signal];
[condition unlock];
}];
while (!hasData) {
[condition wait];
}
[condition unlock];
}