我正在通过Google Places API在搜索栏上集成自动填充功能。对于网络请求,我使用AFNetworking。
我希望一次只运行一个请求。所以每当我输入一封新信时,我都会这样做:
1 - 取消之前的AFHTTPRequestOperation:
[self.currentGlobalSearchListRequest cancel];
NSLog(@"%@ cancelled", self.currentGlobalSearchListRequest);
2 - 开始新的AFHTTPRequestOperation:
self.currentGlobalSearchListRequest = [searchService getGlobalSearchListItemsForString:searchString inRegion:region delegate:self];
NSLog(@"%@ started", self.currentGlobalSearchListRequest);
这是在请求完成运行时调用的回调:
- (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];
}
有时候我打了断言,所以我调查了一下,发现大多数时候
使用错误代码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>
另外,当调用成功块时,我查看AFHTTPRequestOperation上的属性isCancelled
,但它给了我NO(!!!)
我知道我最终可能只是测试而不是使用NSAssert,但我想找到问题的根源。
您是否曾遇到类似的问题,其中取消实际上并未取消请求?然后调用成功块而不是失败块?这是向AFNetworking团队报告的问题吗?谢谢!
如果它可以提供帮助,请求速度非常快(Google自动填充aPI令人印象深刻......)
答案 0 :(得分:1)
展望AFNetworkingCode
,请参阅AFURLConnectionOperation.m, line 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];
}
似乎你所看到的竞争条件的唯一可能性是操作已经完成([self isFinished]
)。请注意,cancel
和完成块之间的间隔非常小(10毫秒)。也许您可以在尝试取消请求之前检查isFinished
吗?
答案 1 :(得分:0)
众所周知,虽然你在中途取消了线程,但是一个线程函数将变为no,当它启动时,它将完成该方法。所以作为要求。也就是说,如果请求仍然在NSOperationQueue中,您可以取消它,但只要您登顶操作,并且该块是复制,它就会回拨。
如果您不想接受回电话,您可以在回电中告知该请求是否被取消。
希望它会对你有所帮助。