gpt4 book ai didi

objective-c - 使用 NSOperationQueue 或 GCD 进行异步解析

转载 作者:行者123 更新时间:2023-12-01 18:26:43 25 4
gpt4 key购买 nike

我的这个解析操作目前运行良好,但我开始注意到它稍微卡住了我的 UI,所以我正在尝试重构并异步完成此操作。但是我遇到了一些问题,希望有人能指出我正确的方向。这是我当前的(同步)代码:

- (NSArray *)eventsFromJSON:(NSString *)objectNotation
{
NSParameterAssert(objectNotation != nil);
NSData *unicodeNotation = [objectNotation dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *eventsData = [NSJSONSerialization JSONObjectWithData:unicodeNotation options:0 error:&error];

if (eventsData == nil) {
//invalid JSON
return nil;
}

NSArray *events = [eventsData valueForKeyPath:@"resultsPage.results"];
if (events == nil) {
//parsing error
return nil;
}

NSLog(@"events looks like %@", events);
NSMutableArray *formattedEvents = [NSMutableArray arrayWithCapacity:events.count];
for (id object in [events valueForKeyPath:@"event"]) {
Event *event = [[Event alloc] init];
event.latitude = [object valueForKeyPath:@"location.lat"];
event.longitude = [object valueForKeyPath:@"location.lng"];
event.title = [object valueForKeyPath:@"displayName"];
event.venue = [object valueForKeyPath:@"venue.displayName"];
event.ticketsLink = [NSURL URLWithString:[object valueForKeyPath:@"uri"]];
event.artist = [object valueForKeyPath:@"performance.artist.displayName"];
event.date = [object valueForKeyPath:@"start.datetime"];

[formattedEvents addObject:event];
}

return [NSArray arrayWithArray:formattedEvents];

}

我一直在研究 NSOperationQueue,我正在努力寻找解决方案,因为我想从此方法返回一个数组,而操作队列并不意味着有返回值。我也在看 GCD,我有这样的东西:
- (NSArray *)eventsFromJSON:(NSString *)objectNotation
{
dispatch_queue_t backgroundQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);


__block NSMutableArray *mutable = [NSMutableArray array];
dispatch_async(backgroundQueue, ^{
NSParameterAssert(objectNotation != nil);
NSData *unicodeNotation = [objectNotation dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *eventsData = [NSJSONSerialization JSONObjectWithData:unicodeNotation options:0 error:&error];

if (eventsData == nil) {
//invalid JSON
mutable = nil;
}

NSArray *events = [eventsData valueForKeyPath:@"resultsPage.results"];
if (events == nil) {
//parsing error
mutable = nil;
}

NSLog(@"events looks like %@", events);
NSMutableArray *formattedEvents = [NSMutableArray arrayWithCapacity:events.count];
for (id object in [events valueForKeyPath:@"event"]) {
Event *event = [[Event alloc] init];
event.latitude = [object valueForKeyPath:@"location.lat"];
event.longitude = [object valueForKeyPath:@"location.lng"];
event.title = [object valueForKeyPath:@"displayName"];
event.venue = [object valueForKeyPath:@"venue.displayName"];
event.ticketsLink = [NSURL URLWithString:[object valueForKeyPath:@"uri"]];
event.artist = [object valueForKeyPath:@"performance.artist.displayName"];
event.date = [object valueForKeyPath:@"start.datetime"];

[formattedEvents addObject:event];
}

mutable = [NSMutableArray arrayWithArray:formattedEvents];

});

return [mutable copy];
}

出于某种原因,这似乎在解析完成之前返回了对象,因为我没有从该可变对象中获取任何数据,但我注意到解析确实发生了(我正在注销结果)。谁能给我一个关于如何让这些异步的东西运行的想法?

谢谢!!

最佳答案

您的主要问题是,就其本质而言,异步操作无法同步返回结果。而不是从 -eventsFromJSON: 返回一个数组,您应该为调用者提供一种在结果完成时接收回调的方法。在 Cocoa 中有两种常见的方法。

您可以使用关联的委托(delegate)协议(protocol)创建委托(delegate),包括像 -parser:(Parser *)parser didFinishParsingEvents:(NSArray *)events 这样的方法。 ,然后让您的解析器在解析完成时在其委托(delegate)上调用此方法。

另一种解决方案是允许调用者提供一个完成 block ,以便在解析完成时执行。所以,你可能会做这样的事情:

- (void)eventsFromJSON:(NSString *)objectNotation completionHandler:(void (^)(NSArray *events))completionHandler)
{
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(backgroundQueue, ^{
NSMutableArray *mutable = [NSMutableArray array];
NSParameterAssert(objectNotation != nil);
NSData *unicodeNotation = [objectNotation dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;

// Snip...

mutable = [NSMutableArray arrayWithArray:formattedEvents];

dispatch_async(dispatch_get_main_queue(), ^{
completionHandler([mutable copy]);
});
});
}

然后你可以像这样调用这段代码:
 - (void)parseJSONAndUpdateUI // Or whatever you're doing
{
NSString *jsonString = ...;
Parser *parser = [[Parser alloc] init];
[parser parseEventsFromJSON:jsonString completionHandler:^(NSArray *events){
// Update UI with parsed events here
}];
}

我更喜欢第二种基于 block 的方法。在大多数情况下,它可以减少代码。代码也更接近于同步方法,其中方法只返回一个数组,因为使用结果数组的代码只是在方法调用之后(尽管缩进,因为它在完成 block 的范围内)。

关于objective-c - 使用 NSOperationQueue 或 GCD 进行异步解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13017234/

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