如何在 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 2 中取消获取请求 [关闭]

如何在 AppDelegate 中执行 Segue?

是否通过链调用 ASIO 完成处理程序以取消操作?

iOS Swift 如何访问在完成处理程序闭包中创建的数据——在闭包之外

PHP PDO如何在注册时对密码进行哈希处理,然后在登录时“取消哈希”

如何在 iOS uiautomation 中使用两个按钮处理警报