3

在我的 iOS 应用程序中,我有一个启用了分页的 UIScrollView。每个页面显示一个视图(带有多个子视图);任何时候只加载 3 个“页面”——当前查看的页面、左侧的页面和右侧的页面。加载是在后台懒惰地完成的。该应用程序正在使用 ARC。

每个页面上的视图主要由一个图像组成,该图像是从 Core Data 中检索出来的。此图像可能很大,因此先加载缩略图,然后将其替换为较大的图像。这个更大的图像实际上是数据存储中实际内容的缩小版本 - 不同的屏幕需要全分辨率版本,但对于这个图像滚动器,它只需要适合页面即可。实际存储的图像可能要大得多(来自相机的照片为 2448x3264)。请注意,Core Data 中的 image 属性设置为允许外部存储,因此在大多数情况下,它不会存储在 SQLite 数据库中。

一切都“工作正常”:滚动条和图像加载速度很快(首先是缩略图,然后是更大的图像),并且滚动速度很快。根据 Instruments 的说法,内存使用情况也很好——直到第 11 张图像加载,此时内存峰值增加了约 5MB;随后加载的图像可能会导致更多的内存峰值(不是每一个,可能每隔一个会导致另一个 ~5MB 峰值)。没有特定的图像导致峰值(我已经更改了加载图像的顺序,它始终是第 11 个)。这段记忆似乎永远不会被释放。

这是在后台加载图像的代码片段:

- (void)loadImageWithCardInstanceObjectId:(NSManagedObjectID *)cardInstanceObjectId
                           imageIndex:(NSUInteger)imageIndex
              withInitialImageHandler:(void (^)(UIImage *image))initialImageHandler
                withFinalImageHandler:(void (^)(UIImage *image))finalImageHandler
{
    NSManagedObjectContext *tempMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    tempMoc.parentContext = [[DataManager sharedInstance] managedObjectContext];

    [tempMoc performBlock:^{
        CardInstance *ci = (CardInstance *)[tempMoc objectWithID:cardInstanceObjectId];
        if (ci.cardInstanceImages.count == 0) {
            // no card images, return the default image
            dispatch_async(dispatch_get_main_queue(), ^{
                initialImageHandler([UIImage imageNamed:@"CardNoImage.png"]);
            });
            return;
        }

        // have card images, pick the one according to the passed in index
        UIImage *thumbnail = [[ci.cardInstanceImages objectAtIndex:imageIndex] thumbnailRepresentation];
        dispatch_async(dispatch_get_main_queue(), ^{
            initialImageHandler(thumbnail);
        });

        // THIS IS THE OFFENDING LINE
        UIImage *fullImage = [[ci.cardInstanceImages objectAtIndex:imageIndex] imageRepresentation];

        CGSize size = fullImage.size;
        CGFloat ratio = 0;
        if (size.width > size.height) {
            ratio = 240.0 / size.width;
        }
        else {
            ratio = 240.0 / size.height;
        }
        CGRect rect = CGRectMake(0.0, 0.0, ceilf(ratio * size.width), ceilf(ratio * size.height));

        // create the image to display
        UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
        [fullImage drawInRect:rect];
        UIImage *imageToDisplay = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        dispatch_async(dispatch_get_main_queue(), ^{
            finalImageHandler(imageToDisplay);
        });
    }];
}

在工具中,负责分配的库/调用者是 CoreData +[_PFRoutines readExternalReferenceDataFromFile:]。

关于为什么会发生这种内存峰值的任何想法?谢谢

4

0 回答 0