ios - 将 UIImage 绘制为 MKMapView 的 subview 与将其绘制为 map View 中的注释相比,对 CPU 的压力更小。为什么?

标签 ios iphone objective-c cocoa

在 map View 中四处移动一些图像时,我发现将图像包装到注释中——然后四处移动该注释会导致 CPU 的大量使用。

在采用替代方法后,将图像包装到 UIImageView 并将 ImageView 作为 subview 添加到 MKMapViews 的 View 中,“在图像周围移动”可以在几乎 0% 的 CPU 使用率下完成。

为什么?我最初的假设是 subview 是使用 GPU 绘制的,但我找不到任何文档来支持我的假设。

附件是仪器的屏幕截图。第一张图片的蓝色部分表示采用注释方法时的 cpu 使用情况。 High Cpu Usage 第二张图片的蓝色部分显示了采用 UIImageView-as-subview 方法时的 cpu 使用情况。 Low Cpu Usage

两个 UML 图代表每种方法的设计。

注解设计 first design

subview 设计 second design

最后,这里是用于 subview 方法的代码。 不幸的是,注释方法的代码已经丢失。

#pragma mark - Zombie Drawing

/** Draws the zombies found in self.zombiesCoordinates onto the map.
 *  @remark Not the most efficient code but it is very readable. Uses less than 1% cpu on iPhone 4s.
 */
 - (void) displayZombiesOnMap {
// 1. Ensure the zombies have a pairing uiimageview, if not create one.
// 2. Detect if zombie has been deleted, then remove his uiimageview.
// 3. Redraw at correct coordinates.

NSAssert(_mapView != nil, @"Map was nil!");
NSAssert(self.zombiesCoordinates != nil, @"zombieCoordinates dictionary was nil");
#ifdef DEBUG
if (self.zombiesCoordinates.count == 0) {
NSLog(@"%@ : Warning, dictionary empty", NSStringFromSelector(_cmd));
}
#endif
// 1.
// Handle deletion of zombies, by removing UIImageViews which do not belong to any zombie identifier.
for (UIImageView * view in _mapView.subviews) {
  NSNumber *tagOfView =[NSNumber numberWithInteger:view.tag];
  CLLocation *coordinates =[self.zombiesCoordinates objectForKey:tagOfView];
// Map can have multiple subviews. Only concern those of UIImageView class as its used to draw the images.
  if (coordinates == nil &&[view isKindOfClass:[UIImageView class]]) {
    [view removeFromSuperview];
}
}

// 2.
// Create a new UIImageView for new zombies, add it to the map.
NSEnumerator *zombiesKeyEnumerator = self.zombiesCoordinates.keyEnumerator;
id key;
while ((key = zombiesKeyEnumerator.nextObject)) {
BOOL zombieHasAView = FALSE;
NSInteger zombieID =[key integerValue];
for (UIImageView * view in _mapView.subviews) {
    if (view.tag == zombieID) {
    zombieHasAView = YES;
    break;
    }
}

// Create a UIImageView if one does not excist for the current zombie.
if (!zombieHasAView) {
    // Convert the zombies GPS coordinates into coordinates within the MapView.
  CLLocation *geoCoords =[self.zombiesCoordinates objectForKey:key];
    NSAssert(geoCoords != nil, @"geoCoords are nil!");

    // Create the zombie view
    UIImage *zombieImage = IMAGE_ZOMBIE NSAssert(zombieImage != nil, @"Image not found!");
  UIImageView *view =[[UIImageView alloc] initWithImage:zombieImage];
    view.tag = zombieID;

  CGPoint pointInMapView =[_mapView convertCoordinate: geoCoords.coordinate toPointToView:_mapView];
    centerViewAtPoint(view, pointInMapView);

  [_mapView addSubview:view];
}
}

// 3.
// Move views to new locations, to match the new location of zombies.
for (UIImageView * view in _mapView.subviews) {
  if ([view isKindOfClass:[UIImageView class]]) {
  NSNumber *zombieID =[NSNumber numberWithInteger:view.tag];
    NSAssert(zombieID != nil, @"zombieID is nil");

  CLLocation *geoCoords =[self.zombiesCoordinates objectForKey:zombieID];
    NSAssert(geoCoords != nil, @"geoCoords are nil!");

  CGPoint pointInMapView =[_mapView convertCoordinate: geoCoords.coordinate toPointToView:_mapView];
    centerViewAtPoint(view, pointInMapView);
}
}
}

最佳答案

UIViews 使用 Core Animation CALayer 作为它们的支持,并且确实是使用 GPU 绘制的。我不熟悉 MapKit,但很可能注释是作为它覆盖的 map 图 block 的一部分呈现的,这意味着当您移动它时,系统将不得不重新绘制受影响的 map 图 block 。

关于ios - 将 UIImage 绘制为 MKMapView 的 subview 与将其绘制为 map View 中的注释相比,对 CPU 的压力更小。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20402088/

相关文章:

ios - NSTimer 无法在 NSThread 函数中启动或运行?

ios - 如何使用闭包在两个 ViewController 之间传递数据

ios - TableView :cellForRowAtIndexPath never called

iphone - 如何在iphone中给图片添加素描效果?

iphone - 核心数据和线程/Grand Central Dispatch

ios - 触摸打开和关闭灯

ios - UICollectionView 不显示任何图像

ios - 如何从没有扩展名的文件加载图像到 UIImage

c++ - 从 Objective-C 访问静态 C++ 字段

ios - 如何删除屏幕上绘制的图像并释放所有链接以便 ARC 回收?