2012-12-18 38 views
2

这里滚动和Sametime负载的全屏幕图像从资产的东西: 我有一个滚动视图,它确实延迟加载为用户的照片全屏图像:感觉滞后时,在后台线程

[self.assetsLibrary assetForURL:[NSURL URLWithString:[[self.assets objectAtIndex:index] objectForKey:@"asset_url"]] 
    resultBlock:^(ALAsset *asset) { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      CGImageRef cgImage = asset.defaultRepresentation.fullScreenImage; 
      UIImage *image = [UIImage imageWithCGImage:cgImage]; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       imageView.image = image; 
      }); 
     }); 
        } 
failureBlock:^(NSError *error) { 
    NSLog(@"error"); 
}]; 

我知道加载全屏图像是昂贵的,所以我把它放到后台线程中,但是当我执行滚动时它仍然滞后。而仍然落后,即使我改变这样的:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
          CGImageRef cgImage = asset.defaultRepresentation.fullScreenImage; 
          UIImage *image = [UIImage imageWithCGImage:cgImage]; 
          imageView.image = image; 
          dispatch_async(dispatch_get_main_queue(), ^{ 
          }); 
         }); 

显然,没什么可在主队列做,但它仍然落后,直到我的评论行:

// CGImageRef cgImage = asset.defaultRepresentation.fullScreenImage; 

所以我很困惑,当我使用GCD时有什么问题吗?有人可以帮我解释一下吗?任何事情都会有所帮助。

谢谢,伙计们。

UPDATE

要@Fogmeister:照片的尺寸是目前全屏幕大小,actuel ImageView的大小大约是一半。即使我评论这一行:“imageView.image = image;”它仍然滞后。这意味着它不是从调整大小。我知道时间在哪里,在这里:“asset.defaultRepresentation.fullScreenImage;”。当我评论它时,一切都很好,没有更多的滞后。 所以,我不明白的是,我已经把它放在后台线程中...

回答

5

好吧,我终于解决了问题:

,而不是由

asset.defaultRepresentation.fullScreenImage 

直接获取图像我使用苹果为例PhotosByLocation(下面的代码)的方法来获得BG线的图像。这样做效果很好,滚动时没有更多滞后。 但我仍然感到困惑,我不知道为什么。所以我很感激有人能向我解释。从苹果公司的PhotosByLocation采取

- (UIImage *)fullSizeImageForAssetRepresentation:(ALAssetRepresentation *)assetRepresentation { 

UIImage *result = nil; 
NSData *data = nil; 

uint8_t *buffer = (uint8_t *)malloc(sizeof(uint8_t)*[assetRepresentation size]); 
if (buffer != NULL) { 
    NSError *error = nil; 
    NSUInteger bytesRead = [assetRepresentation getBytes:buffer fromOffset:0 length:[assetRepresentation size] error:&error]; 
    data = [NSData dataWithBytes:buffer length:bytesRead]; 

    free(buffer); 
} 

if ([data length]) { 
    CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil); 

    NSMutableDictionary *options = [NSMutableDictionary dictionary]; 

    [options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceShouldAllowFloat]; 
    [options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceCreateThumbnailFromImageAlways]; 
    [options setObject:(id)[NSNumber numberWithFloat:640.0f] forKey:(id)kCGImageSourceThumbnailMaxPixelSize]; 
    //[options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceCreateThumbnailWithTransform]; 

    CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options); 

    if (imageRef) { 
     result = [UIImage imageWithCGImage:imageRef scale:[assetRepresentation scale] orientation:(UIImageOrientation)[assetRepresentation orientation]]; 
     CGImageRelease(imageRef); 
    } 

    if (sourceRef) CFRelease(sourceRef); 
} 

return result; 
} 
0

你知道照片的实际大小吗?什么是非常昂贵的滚动正在调整大小,以适应屏幕的图像。

鉴于您已经加载了一个BG线程,可能需要将图像调整为您在显示它的大小之前将其粘贴在屏幕上。

通过使用Xcode中的应用程序分析应用程序,您可以通过在乐器中使用CoreAnimation工具来了解从何处获取时间。它甚至会告诉你哪一行代码导致了减速和错过的动画帧。

+0

谢谢你的回复。是的,照片的大小是全屏尺寸,实际尺寸是大约一半。即使我评论这一行:“imageView.image = image;”它仍然滞后。这意味着它不是从调整大小。我知道时间在哪里,在这里:“asset.defaultRepresentation.fullScreenImage;”。当我评论它时,一切都很好,没有更多的滞后。我不明白的是,我已经在bg线程中执行了它... – swang

+0

如果您在仪器中使用时间分析器工具进行配置文件,您将开始看到为什么它在特定线路上很慢。绝对值得一试。 – Fogmeister

+0

谢谢,我试过了。最后,我从Appel的例子中解决了这个问题。我发布了答案。但我不明白为什么这样... – swang

0

从苹果文档:

DISPATCH_QUEUE_PRIORITY_DEFAULT
Items dispatched to the queue run at the default priority; the queue is scheduled for execution after all high priority queues have been scheduled, but before any low priority queues have been scheduled.

DISPATCH_QUEUE_PRIORITY_BACKGROUND
Items dispatched to the queue run at background priority; the queue is scheduled for execution after all high priority queues have been scheduled and the system runs items on a thread whose priority is set for background status. Such a thread has the lowest priority and any disk I/O is throttled to minimize the impact on the system.

你在一个单独的线程中运行它,但这不一定是线程“的背景。”根据我的经验加载某个后台线程将会通过执行UI更新(例如滚动UIScrollView)而被完全阻止。你有没有试过用DISPATCH_QUEUE_PRIORITY_BACKGROUND

+0

谢谢你的答复。我试过了,但仍然有问题。 – swang

1

你的解决方案其实就是抓住了最大分辨率的图像,而不是全屏图像。 IOW,它与调用fullResolutionImage而不是fullScreenImage基本相同。如何解决你的问题,我不确定。我正在努力解决同样的性能问题。如果我使用fullScreenImage,那么在滚动时会出现滞后现象。但切换到fullResolutionImage可以消除时滞。 fullResolutionImage大约是fullScreenImage的两倍,但由于它总是在后台,所以花费多少时间应该不会有问题。我怀疑fullScreenImage返回的图像需要一些额外的处理,一旦它被渲染到主线程中的屏幕 - 因此滞后。