【问题标题】:iOS Map Annotation IssueiOS 地图注释问题
【发布时间】:2013-12-18 22:37:21
【问题描述】:

我有一个地图视图,上面有几个注释和一个搜索栏。在 iOS 6 中一切正常,但在 iOS 7 中存在问题。在 iOS 7 中,当我选择一个图钉时,会弹出标题,我可以点击信息按钮转到该位置的详细视图。问题是当我在 iOS 7 上搜索时,作为搜索结果的注释在注释周围出现黑色区域​​,我无法点击信息按钮。

这里是在不搜索的情况下选择一个图钉:

这是在搜索之后:

这是我搜索时发生的代码:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    id<MKAnnotation> ann;
    BOOL annotationFound = NO;
    // NSRange titleRange = [annTitle rangeOfString:searchText options:NSCaseInsensitiveSearch];
    // NSRange subtitleRange = [annSubtitle rangeOfString:searchText options:NSCaseInsensitiveSearch];

    for (int i = 0; i < [marketLocations count]; i++)
    {
        for (ann in marketLocations)
        {
            NSString *annTitle = ann.title;
            NSString *annSubtitle = ann.subtitle;
            NSString *searchText = [searchBar text];
            NSRange titleRange = [annTitle rangeOfString:searchText options:NSCaseInsensitiveSearch];
            NSRange subtitleRange = [annSubtitle rangeOfString:searchText options:NSCaseInsensitiveSearch];
            CLLocationCoordinate2D annCoord;
            annCoord.latitude = ann.coordinate.latitude;
            annCoord.longitude = ann.coordinate.longitude;

            // if ([ann.title isEqualToString:[searchBar text]])
            if (titleRange.location != NSNotFound)
            {
                MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annCoord, 5000, 5000);
                [worldView setRegion:region animated:YES];
                [worldView selectAnnotation:ann animated:YES];
                annotationFound = YES;
            }
            // else if ([ann.subtitle isEqualToString:[searchBar text]])
            else if (subtitleRange.location != NSNotFound)
            {
                MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annCoord, 5000, 5000);
                [worldView setRegion:region animated:YES];
                [worldView selectAnnotation:ann animated:YES];
                annotationFound = YES;
            }
        }
    }
    if (annotationFound == NO)
    {
        UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"" message:@"No Matches Found" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [av dismissWithClickedButtonIndex:0 animated:YES];
        [av show];
    }

    [searchBar resignFirstResponder];
}

【问题讨论】:

    标签: ios objective-c ios7 annotations mkmapview


    【解决方案1】:

    显示的搜索代码有两个奇怪的地方,我相信它们都有助于导致奇怪的显示问题:

    1. 外部for 循环通过marketLocations 数组,内部for 循环 通过marketLocations 数组。

      这种嵌套似乎没有必要,并且会导致搜索执行的迭代次数超出您的需要。

      如果有 100 个注释,则搜索将执行 100 x 100 次迭代 (10,000) 而不是仅 100 次(因为循环中没有 breaks)。当注释不止几个时,您可能会注意到搜索稍有延迟。

      看起来您只需要一个 for 循环。

    2. 当找到“匹配”注解时,代码调用setRegionselectAnnotation(两者都涉及更新显示)然后继续搜索循环。

      在您已经调用selectAnnotation 之后继续搜索更多匹配的注释是没有意义的,因为无论如何地图视图一次只允许“选择”一个注释(显示标注)。

      一旦找到匹配的注释,您应该break 循环,或者跟踪“最佳匹配注释”并在搜索循环之后调用setRegionselectAnnotation。 p>


    我相信数百(可能数千)次迭代的非常紧密的循环以及对setRegionselectAnnotation 的多次快速调用导致了这个显示问题。我能够用 100 个注释复制它。

    为什么它只出现在 iOS 7 中是我无法回答的问题,但我怀疑 iOS 6 对此是否满意(只是没有显示)。

    所以我的建议是:

    1. 使用单个 for 循环,并且,
    2. 假设您想在第一个“匹配”处停止,请在调用 selectAnnotation 后立即执行 break 以停止循环。

    代码可能如下所示:

    - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
    {
        id<MKAnnotation> ann;
        BOOL annotationFound = NO;
    
        // SINGLE for-loop...
        for (ann in marketLocations)
        {
            NSString *annTitle = ann.title;
            NSString *annSubtitle = ann.subtitle;
            NSString *searchText = [searchBar text];
            NSRange titleRange = [annTitle rangeOfString:searchText options:NSCaseInsensitiveSearch];
            NSRange subtitleRange = [annSubtitle rangeOfString:searchText options:NSCaseInsensitiveSearch];
            CLLocationCoordinate2D annCoord;
            annCoord.latitude = ann.coordinate.latitude;
            annCoord.longitude = ann.coordinate.longitude;
    
            if (titleRange.location != NSNotFound)
            {
                MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annCoord, 5000, 5000);
                [worldView setRegion:region animated:YES];
                [worldView selectAnnotation:ann animated:YES];
                annotationFound = YES;
                break;  // <-- STOP searching, exit the loop
            }
            else if (subtitleRange.location != NSNotFound)
            {
                MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annCoord, 5000, 5000);
                [worldView setRegion:region animated:YES];
                [worldView selectAnnotation:ann animated:YES];
                annotationFound = YES;
                break;  // <-- STOP searching, exit the loop
            }
        }
    
        if (annotationFound == NO)
        {
            UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"" message:@"No Matches Found" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [av dismissWithClickedButtonIndex:0 animated:YES];
            [av show];
        }
    
        [searchBar resignFirstResponder];
    }
    

    【讨论】:

    • 看起来只有当注释结果是它找到的最后一个匹配结果并且因此是显示的结果时才会出现问题。如果我在其中添加中断,则问题不会出现。问题在于我的搜索结果虽然在技术上是正确的,但并不是我想要的。例如,如果我搜索 haney,则在那里出现中断,我会得到 chaney 的注释,因为它首先到达它。
    • 对,所以你必须先遍历所有注解找到“最佳匹配”,然后在循环结束后对其调用 selectAnnotation。
    • 我不确定如何找到最佳匹配。
    • 您现有的逻辑(没有break)基本上是使用 last 匹配作为要选择的匹配项(即使最后一个是“chaney”并且您正在搜索为“哈尼”)。如何选择“最佳”匹配取决于您,但总体思路是这样的(在进一步的 cmets 中给出):
    • 1) 在循环之前,声明另一个名为bestAnn 的注解变量并将其设置为nil。 2)在循环中,当您找到“匹配”时,如果bestAnnnil,则将bestAnn 设置为新匹配,否则将新匹配与bestAnn 进行比较,如果新匹配比“更好” bestAnn 设置 bestAnn 等于新匹配并继续循环。 3) 循环之后,如果bestAnn 为nil,则显示您的警报视图,否则,使用bestAnn.coordinate 调用setRegion,使用bestAnn 调用selectAnnotation。您将不需要 annotationFound 变量。
    【解决方案2】:

    我实际上找到了一个非常简单的解决方法。而不是

    NSRange titleRange = [annTitle rangeOfString:searchText options:NSCaseInsensitiveSearch];

    我已经改成

    NSRange titleRange = [annTitle rangeOfString:searchText];

    并设置

    searchBar.autocapitalizationType = UITextAutocapitalizationTypeWords;
    

    【讨论】:

      猜你喜欢
      • 2011-05-21
      • 2011-01-29
      • 2015-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      • 2023-03-23
      • 1970-01-01
      相关资源
      最近更新 更多