gpt4 book ai didi

AFNetworking 后台JSON解析避免 block 嵌套

转载 作者:行者123 更新时间:2023-12-04 17:31:05 27 4
gpt4 key购买 nike

我有一些正在进行大量 JSON 解析的网络代码。需要在后台进行才能不阻塞主线程。代码如下所示:

-(void) getSomeDataWithParameters:(...)parameters completion:(void (^)(NSArray *data))completion
{
NSURLRequest *req = ...
AFJSONRequestOperation *op = [[AFJSONRequestOperation alloc] initWithRequest:req];

// sometimes I have more requests

// startOperations is a wrapper on AFHTTPClient enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:
// that handles errors and loading views
[self startOperations:@[op] completionBlock:^(NSArray *operations) {

// getBgQueue = return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(getBgQueue(), ^{

NSArray *data = [MyParserClass parseJSON:op.responseJSON inContext:self.localContext];

[self.localContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
// this is executed on main thread
if(completion) completion(...);
}];

});

}];
}

(AFNetworking 1.x)

上面的代码工作得很好,但是设置和编写起来很痛苦。并且通常整个方法内容都被包裹在另一个块中以首先获取一些所需的数据......基本上这些块只是堆积起来并产生丑陋的代码

我正在使用 enqueueBatchOfHTTPRequestOperations而不是 AFJSONRequestOperation 上的单个完成块因为批处理完成块有时会在所有单个操作完成块之前触发......(我也在某处读到 Mattt 不鼓励这样做)

关于如何做得比这更好的任何指示?

最佳答案

我不确定你在这里想要什么,但就像“longcat is long”一样,它在模式中有些固有:'continuation-passing style is continuation-passing style'。如果你想把事情弄平一点,你可以创建局部块变量,但在某种程度上,你被卡住了,因为你需要完成 -MR_saveToPersistentStoreWithCompletion收尾 data以便将其传递给 -getSomeDataWithParameters...完成,但 data直到 -startOperations 才会存在完成被执行。

您可能可以通过使用一堆 __block 来获得较少嵌套的外观。变量,并将代码拆分为几个局部块,但对我来说,这感觉有点像切掉 Nose 来冒犯你的脸。这段代码很容易理解。

顺便说一句...我注意到你正在关闭 op-startOperations完成块。这很好,因为您正在排队 op通过做-startOperations: @[op] ...但可以说得到 op 会更干净来自 operations参数完成。我尽可能地收紧了这一点:

- (void)getSomeDataWithParameters:(...)parameters completion:(void (^)(NSArray *data))completion
{
NSURLRequest *req = ...;
AFJSONRequestOperation *op = [[AFJSONRequestOperation alloc] initWithRequest:req];

[self startOperations:@[op] completionBlock:^(NSArray *operations) {
for (AFJSONRequestOperation *op in operations) {
dispatch_async(getBgQueue(), ^{
NSArray *data = [MyParserClass parseJSON:op.responseJSON inContext:self.localContext];
void (^mrSaveCompletion)(BOOL, NSError*) = completion ? ^(BOOL success, NSError *error) { completion(data); } : nil;
[self.localContext MR_saveToPersistentStoreWithCompletion: mrSaveCompletion];
});
}
}];
}

这会将每个响应可能分散到不同的线程。如果您希望所有响应都在单个后台线程上执行,只需交换 for 的嵌套即可。循环和 dispatch_async .

从那里开始,唯一真正“多余”的代码是 dispatch_async .您可以通过制作 -startOperations:... 来消除这种情况。取一个队列参数,您将在其中传递您希望调用完成的队列。也许是这样的:
- (void)startOperations: (NSArray*)ops completionQueue: (dispatch_queue_t)queue completionBlock: (void (^)(NSArray*))completion
{
void (^completionWrapper)(NSArray*) = !completion ? nil : ^(NSArray* ops) {
if (queue)
dispatch_async(queue, ^{ completion(ops); });
else
completion(ops);
};

[self startOperations: ops completionBlock: completionWrapper];
}

- (void)getSomeDataWithParameters:(...)parameters completion:(void (^)(NSArray *data))completion
{
NSURLRequest *req = ...;
AFJSONRequestOperation *op = [[AFJSONRequestOperation alloc] initWithRequest:req];
[self startOperations:@[op] completionQueue: getBgQueue() completionBlock:^(NSArray *operations) {
for (AFJSONRequestOperation *op in operations) {
NSArray *data = [MyParserClass parseJSON:op.responseJSON inContext:self.localContext];
void (^mrSaveCompletion)(BOOL, NSError*) = !completion ? nil : ^(BOOL success, NSError *error) { completion(data); };
[self.localContext MR_saveToPersistentStoreWithCompletion: mrSaveCompletion];
});
}];
}

关于AFNetworking 后台JSON解析避免 block 嵌套,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20117618/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com