MapView - 一次出现一个注释

时间:2011-07-06 02:33:21

标签: iphone annotations android-mapview

我目前正在通过循环向地图添加注释......但注释仅出现在我的地图上。此外,在加载时,地图上实际上只显示了大约4个注释...但是当我稍微移动地图时,应该存在的所有注释突然出现。

如何在正确的位置加载所有注释,一次一个?

提前致谢!

以下是我用来添加注释的代码:

 NSString *incident;
            for (incident in weekFeed) {
                NSString *finalCoordinates = [[NSString alloc] initWithFormat:@"%@", [incident valueForKey:@"coordinates"]];

                NSArray *coordinatesArray = [finalCoordinates componentsSeparatedByString:@","]; 

                latcoord = (@"%@", [coordinatesArray objectAtIndex:0]);
                longcoord = (@"%@", [coordinatesArray objectAtIndex:1]);

                // Final Logs
                NSLog(@"Coordinates in NSString: [%@] - [%@]", latcoord, longcoord);

                CLLocationCoordinate2D coord;
                coord.latitude = [latcoord doubleValue];
                coord.longitude = [longcoord doubleValue];


                DisplayMap *ann = [[DisplayMap alloc] init]; 
                ann.title = [NSString stringWithFormat: @"%@", [incident valueForKey:@"incident_type"]];
                ann.subtitle = [NSString stringWithFormat: @"%@", [incident valueForKey:@"note"]];
                ann.coordinate = coord;

                [mapView addAnnotation:ann];

                [ann release];
                }


// Custom Map Markers
-(MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation {

    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;  //return nil to use default blue dot view

    static NSString *AnnotationViewID = @"annotationViewID";
    MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];

    if (annotationView == nil) {
        annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID] autorelease];
        }

    annotationView.canShowCallout = YES;

    if ([annotationView.annotation.title isEqualToString:@"one"]) {
        UIImage *pinImage = [UIImage imageNamed:@"marker_1.png"];
        [annotationView setImage:pinImage];
        }

    if ([annotationView.annotation.title isEqualToString:@"two"]) {
        UIImage *pinImage = [UIImage imageNamed:@"marker_2.png"];
        [annotationView setImage:pinImage];
        }

    annotationView.annotation = annotation;
    return annotationView;
    }

- (void) mapView:(MKMapView *)mapV didAddAnnotationViews:(NSArray *)views {
    CGRect visibleRect = [mapV annotationVisibleRect]; 
    for (MKAnnotationView *view in views) {
        CGRect endFrame = view.frame;

        CGRect startFrame = endFrame; startFrame.origin.y = visibleRect.origin.y - startFrame.size.height;
        view.frame = startFrame;

        [UIView beginAnimations:@"drop" context:NULL]; 
        [UIView setAnimationDuration:0.4];

        view.frame = endFrame;

        [UIView commitAnimations];
    }
}

2 个答案:

答案 0 :(得分:1)

亚当,

这个解决方案有点乱,因为我不得不把我当前的一个项目用来测试,但希望这对你有用。

首先解释一下,将数据与UI表示分开至关重要。 [MKMapView addAnnotation(s)]只是对MKMapView的数据更新,对动画或计时没有直接影响。

委托方法mapView:didAddAnnotationViews:应该定义所有自定义表示行为。在您的描述中,您不希望这些一次全部显示,因此您需要对动画进行排序,而不是同时执行它们。

一种方法是一次性添加所有注释,然后只需添加动画延迟,但无论出于何种原因添加的新注释都会再次以零开始动画。

下面的方法设置一个动画队列self.pendingViewsForAnimation(NSMutableArray)来保存注释视图,然后按顺序链接动画。

我用alpha替换了帧动画,专注于动画问题,将其与一些未出现的项目分开。在代码之后更多关于此...

// Interface
// ...

// Add property or iVar for pendingViewsForAnimation; you must init/dealloc the array
@property (retain) NSMutableArray* pendingViewsForAnimation;

// Implementation
// ...
- (void)processPendingViewsForAnimation
{
    static BOOL runningAnimations = NO;
    // Nothing to animate, exit
    if ([self.pendingViewsForAnimation count]==0) return;
    // Already animating, exit
    if (runningAnimations) 
        return;

    // We're animating
    runningAnimations = YES;

    MKAnnotationView* view = [self.pendingViewsForAnimation lastObject];

    [UIView animateWithDuration:0.4 animations:^(void) {
        view.alpha = 1;
        NSLog(@"Show Annotation[%d] %@",[self.pendingViewsForAnimation count],view);
    } completion:^(BOOL finished) {
        [self.pendingViewsForAnimation removeObject:view];
        runningAnimations = NO;
        [self processPendingViewsForAnimation];
    }];

}

// This just demonstrates the animation logic, I've removed the "frame" animation for now
// to focus our attention on just the animation.    
- (void) mapView:(MKMapView *)mapV didAddAnnotationViews:(NSArray *)views {
    for (MKAnnotationView *view in views) {
        view.alpha = 0;

        [self.pendingViewsForAnimation addObject:view];
    }
    [self processPendingViewsForAnimation];
}

关于第二个问题,在移动地图之前,项目并不总是出现。我没有在你的代码中看到任何明显的错误,但是我会采取一些措施来解决问题:

  1. 暂时删除mapView:didAddAnnotationViews:,mapView:annotationForView:以及任何其他自定义行为,以查看默认行为是否有效。
  2. 确认您在addAnnotation:调用时有一个有效的注释,并且坐标是可见的(使用[mapView visibleMapRect],MKMapRectContainsPoint()和MKMapPointForCoordinate()。
  3. 如果它仍然无法运行,请查看您从哪里调用添加注释代码。我尝试通过使用performSelector:withObject:afterDelay避免在地图移动期间进行注释调用。您可以在[NSObject cancelPreviousPerformRequestsWithTarget:selector:object:]之前创建一个轻微的延迟,以便在使用多次滑动移动地图长距离时加载注释。
  4. 最后一点,要实现您正在寻找的针脚效果,您可能希望偏离原始对象的固定距离,而不是依赖于注释VisibleRect。您当前的实施将导致引脚以不同的速度移动,具体取决于它们与边缘的距离。顶部的物品将慢慢移动到位,而底部的物品将快速飞到原位。 Apple的默认动画总是从同一高度下降。这里有一个例子:How can I create a custom "pin-drop" animation using MKAnnotationView?

    希望这会有所帮助。

    <强>更新 为了演示此代码的实际应用,我附上了Apple的Seismic演示版修改版的链接,并进行了以下更改:

    1. 将Earthquake.h / m更改为MKAnnotation对象
    2. 使用上面的代码
    3. 添加了SeismicMapViewController.h / m
    4. 更新了RootViewController.h / m以打开地图视图作为模态页面
    5. 请参阅:http://dl.dropbox.com/u/36171337/SeismicXMLWithMapDelay.zip

答案 1 :(得分:0)

添加每个注释后,您需要暂停更新,并允许地图有时间刷新。