为什么取消AFHTTPRequestOperation有时会成功阻止?

Aur*_*rte 7 ios afnetworking afhttprequestoperation

我正在通过Google Places API在搜索栏上集成自动填充功能.对于网络请求,我使用AFNetworking.

我想一次只运行一个请求.所以每次我输入一封新信,我都会做以下事情:

1 - 取消之前的AFHTTPRequestOperation:

[self.currentGlobalSearchListRequest cancel];
NSLog(@"%@ cancelled", self.currentGlobalSearchListRequest);
Run Code Online (Sandbox Code Playgroud)

2 - 开始新的AFHTTPRequestOperation:

self.currentGlobalSearchListRequest = [searchService getGlobalSearchListItemsForString:searchString inRegion:region delegate:self];
NSLog(@"%@ started", self.currentGlobalSearchListRequest);
Run Code Online (Sandbox Code Playgroud)

这是在请求完成运行时调用的回调:

- (void)request:(PointSearchRequest *)request didLoadSearchListItems:(NSArray *)searchListItems {
    NSAssert(request == self.currentGlobalSearchListRequest, @"!!!callback from a request that should be cancelled!!!");
    [self.delegate searchListLoader:self didLoadGlobalSearchList:searchListItems];
}
Run Code Online (Sandbox Code Playgroud)

有时候我打了断言,所以我调查了一下,发现大多数时候用一个错误代码来调用失败块,NSURLErrorCancelled这是预期的行为,但有时会调用成功块!

这个堆栈跟踪告诉我,我的代码中的内容以正确的顺序发生

2013-12-22 09:38:46.484 Point[63595:a0b] <PointSearchRequest: 0x18202b50> started
2013-12-22 09:38:46.486 Point[63595:a0b] <PointSearchRequest: 0x18202b50> cancelled
2013-12-22 09:38:46.487 Point[63595:a0b] <PointSearchRequest: 0x181a5dd0> started
2013-12-22 09:38:46.496 Point[63595:a0b] *** Assertion failure in -[SearchListLoader request:didLoadSearchListItems:], /Users/aurelienporte/Documents/Developpement/Perso/iOS/Point/Point/Classes/Models/SearchListLoader.m:82
(lldb) po request
<PointSearchRequest: 0x18202b50>
Run Code Online (Sandbox Code Playgroud)

另外,isCancelled当调用成功块时我查看AFHTTPRequestOperation 上的属性但是它给了我NO(!!!)我知道我最终可能只是测试而不是使用NSAssert但是想找到问题的根源.

你有没有遇到类似的问题,取消实际上没有取消请求?然后调用成功块而不是失败块?这是向AFNetworking团队报告的问题吗?谢谢!

如果它可以提供帮助,请求速度非常快(谷歌自动完成aPI令人印象深刻...)

Sul*_*han 1

查看AFURLConnectionOperation.m AFNetworkingCode第 461 行

- (void)cancel {
    [self.lock lock];
    if (![self isFinished] && ![self isCancelled]) {
        [super cancel];

        if ([self isExecuting]) {
            [self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
        }
    }
    [self.lock unlock];
}
Run Code Online (Sandbox Code Playgroud)

看来您看到的竞争条件的唯一可能性是操作已经完成的情况 ( [self isFinished])。请注意,您的块和完成块之间的间隔cancel非常小(10 毫秒)。也许您可以isFinished在尝试取消请求之前检查一下?