如何在 iOS 中取消完成处理程序
Posted
技术标签:
【中文标题】如何在 iOS 中取消完成处理程序【英文标题】:How to cancel a completion handler in iOS 【发布时间】:2015-07-30 08:46:20 【问题描述】:我想使用 mapkit 框架获取附近位置的数组。因此,当用户在文本字段中键入时,我会调用以下函数。
- (void)searchForLocations:(NSString *)string
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(search:) object:nil];
[self performSelectorInBackground:@selector(search:) withObject:string];
- (void)search :(NSString *)string
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = string;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = newLocation.coordinate;
request.region = region;
MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error)
if (response.mapItems.count == 0)
NSLog(@"No Matches");
else
NSLog(@"name = %@", item.name);
NSLog(@"Phone = %@", item.phoneNumber);
];
如您所见,如果有新的输入文本出现,我想取消之前的搜索。但是之前的搜索并没有取消。如何取消之前的搜索?
提前致谢。
【问题讨论】:
【参考方案1】:在 MKLocalSearch 上有一个 cancel method。你试过那个吗?
编辑:啊,对不起,我是愚蠢的。您需要以某种方式保留对旧搜索的引用才能取消它。将其放在搜索完成时可以清除(即设置为 nil)的属性中。每当你调用搜索函数时,取消之前的搜索函数(不需要“if”,nil 吞没所有),然后创建一个新的
@property (nonatiomic, strong) MKLocalSearch *previousSearch;
- (void)search :(NSString *)string
[self.previousSearch cancel];
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = string;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = newLocation.coordinate;
request.region = region;
MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error)
self.previousSearch = nil;
if (response.mapItems.count == 0)
NSLog(@"No Matches");
else
NSLog(@"name = %@", item.name);
NSLog(@"Phone = %@", item.phoneNumber);
];
self.previousSearch = search;
【讨论】:
我不明白为什么它会在我的案例中显示以前的搜索结果。【参考方案2】:MKLocalSearch
对象有一个cancel
方法,您可以使用该方法取消挂起的搜索。您不能像尝试那样简单地取消选择器,因为该选择器将很快完成,MKLocalSearch
在后台调度。
您将需要一个属性来存储您的搜索对象,以便您可以判断它是否仍在搜索并在需要时取消搜索。
@property (strong,nonatomic) MKLocalSearch *localSearch;
- (void)search :(NSString *)string
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = string;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = newLocation.coordinate;
request.region = region;
if (self.localSearch!=nil)
if (self.localSearch.searching)
[self.localSearch cancel];
self.localSearch=nil;
self.localSearch = [[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error)
if (response.mapItems.count == 0)
NSLog(@"No Matches");
else
NSLog(@"name = %@", item.name);
NSLog(@"Phone = %@", item.phoneNumber);
];
【讨论】:
【参考方案3】:你可以使用 NSBlockOperation。 假设您用于 NSBlockOperation 的全局变量是 blockOperation。然后:
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error)
blockOperation = NSBlockOperation(block: () -> Void in
if (response.mapItems.count == 0)
NSLog(@"No Matches");
else
NSLog(@"name = %@", item.name);
NSLog(@"Phone = %@", item.phoneNumber);
)
];
然后你可以使用这个blockOperation来取消你想要的任何地方,如下所示:
blockOperation.cancel()
【讨论】:
以上是关于如何在 iOS 中取消完成处理程序的主要内容,如果未能解决你的问题,请参考以下文章
iOS Swift 如何访问在完成处理程序闭包中创建的数据——在闭包之外