我有一个执行webservice调用的块队列。问题是在块结束后没有释放下载的数据。我读了很多关于保留的内容,但我无法让ARC成为记忆。
以下是代码:
创建下载数据的块队列
- (void)syncData
{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_async(queue, ^{
[Model syncAziende:^(id response, NSError *error) {
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
[Model syncContatti:^(id response, NSError *error) {
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
[Model syncDestinazioni:^(id response, NSError *error) {
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
and so on...
});
}
在Model.m
上+ (void)syncAziende:(RequestFinishBlock)completation
{
__weak typeof(self)selfObject = self;
[selfObject syncData:^(id response, NSError *error) {
completation(response,error);
} wsEndPoint:kCDCEndPointGetAziende tableName:kCDCDBAziendeTableName];
}
+ (void)syncContatti:(RequestFinishBlock)completation
{
__weak typeof(self)selfObject = self;
[selfObject syncData:^(id response, NSError *error) {
completation(response,error);
} wsEndPoint:kCDCEndPointGetContatti tableName:kCDCDBContattiTableName];
}
// and so on...
syncData
的位置:
+ (void)syncData:(RequestFinishBlock)completation wsEndPoint:(NSString*) url tableName:(NSString *)table
{
__weak typeof(self)selfObject = self;
[selfObject getDataFromWS:^(id WSresponse, NSError* WSError)
{
completation(nil,nil);
}WSUrl:url];
}
getDataFromWS
的位置:
+ (void)getDataFromWS:(RequestFinishBlock)completation WSUrl:(NSString *)svcUrl
{
__weak typeof(self)selfObject = self;
[selfObject getJsonDataFromURL:^(id response, NSError *error)
{
completation(response,error);
}url:svcUrl];
}
getJsonDataFromURL
的位置:
+(void)getJsonDataFromURL:(RequestFinishBlock)completation url:(NSString*)url
{
__weak typeof(self)selfObject = self;
__weak AFHTTPRequestOperationManager *manager = [selfObject getAuthorizedRequestionOperationManager];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, __weak id responseObject) {
completation([responseObject objectForKey:@"d"],nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
completation(nil,error);
}];
}
答案 0 :(得分:0)
这些__weak
引用在类方法的上下文中并不真正有意义。在处理实例方法时使用weak
- self
模式才有意义。
所以,这就引出了一个问题,即你担心哪个对象没有被释放。我在这里看不到会导致保留syncData
作为实例方法的对象的任何内容。
话虽如此,通过使用信号量使您同步的一系列网络请求的这个例程将(a)保留在整个过程中实例化的任何自动释放对象(特别是操作本身); (b)一旦开始,不允许您取消该过程; (c)连续执行请求(对此您将支付严重的性能损失,除非您绝对必须,否则应该避免)。
我建议简化代码。我将使用信号量消除调度代码。我也在类方法中删除了weak
对self
的所有引用。
您只需发出GET
次请求即可。如果您确实需要它们以串行方式运行(正如您使用信号量所暗示的那样),那么只需将maxConcurrentOperationCount
设置为1
operationQueue
实例的AFHTTPRequestOperationManager
即可。但是,除非你必须这样做,否则不要让它们连续运行,因为你这样做会给性能带来很大的损失。但是可以利用AFNetworking提供的NSOperationQueue
,而不是使用自己的GCD代码(更糟糕的是,使用该GCD代码中的信号量)。
但是这样,如果您要取消请求,则可以为cancelAllOperations
的{{1}}致电operationQueue
。您还可以使用AFHTTPRequestOperationManager
来控制并发度。
答案 1 :(得分:0)
鉴于你的描述并基于评论,一个天真 - 但仍然不足 - 解决方案可能如下所示:
//通用完成处理程序: typedef void(^ completion_t)(id result,NSError * error);
- (void) fetchJSONFromURL:(NSURL*)url completion:(completion_t)completion;
- (void) syncAziendeWithInput:(id)input completion:(completion_t)completion;
- (void) syncContattiWithInput:(id)input completion:(completion_t)completion;
- (void) syncDestinazioniWithInput:(id)input completion:(completion_t)completion;
- (void) syncData
{
dispatch_queue_t sync_queue = dispatch_queue_create("sync_queue", 0); // serial queue
NSURL* url = ...;
[self fetchJSONFromURL:url completion:^(id result, NSError*error){
dispatch_async(sync_queue, ^{
[self syncAziendeWithInput:result completion:^(id result, NSError* error){
...
}];
});
}];
url = ...;
[self fetchJSONFromURL:url completion:^(id result, NSError*error){
dispatch_async(sync_queue, ^{
[self syncContattiWithInput:result completion:^(id result, NSError* error){
...
}];
});
}];
url = ...;
[self fetchJSONFromURL:url completion:^(id result, NSError*error){
dispatch_async(sync_queue, ^{
[self syncDestinazioniWithInput:result completion:^(id result, NSError* error){
...
}];
});
}];
...
}
<强>注意事项:强>
简单化。一个实用的解决方案变得更加精细:
尚无错误处理。
无法取消异步任务。
syncData
是异步的,但没有完成处理程序。也就是说,我们不知道什么时候完成。我们可以利用dispatch_group
来实现一种方法来表示许多异步方法的完成。
在第三方库的帮助下,我们可以实现一个完成上述所有工作的解决方案,看起来基本上更简单。