0

这是在drawRect里面:

NSString *generated = [Entry generateString];

const char *cString = (const char*)[generated UTF8String];

dispatch_queue_t queue = dispatch_queue_create(cString, NULL);*/

dispatch_async(queue, ^{

    Media *media = [self.entry.media objectAtIndex:i];

    UIImage *image = [media getThumbnail];

    dispatch_async(dispatch_get_main_queue(), ^{

        int bottom = [JHomeViewCell yOfMessageBottomWithMessageHeight:self.cellInfo.messageHeight
                                                            withMonth:self.cellInfo.hasMonth];

        CGRect frame = CGRectMake(87 + (68 * i),
                                  bottom,
                                  THUMBNAIL_SIZE.width,
                                  THUMBNAIL_SIZE.height);

        [image drawInRect:frame];
    });

});

现在,它在 objectAtIndex 行崩溃。这不是一个无效的索引。该代码在此之外工作正常。

编辑:我收到了这个错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'statement is still active'

编辑 2:我放入 NSLogs,第一个获得 media.count。它因同样的错误而崩溃。

4

1 回答 1

6

这里的问题是你画在你应该在的地方之外。当你从 回来时drawRect:,你已经告诉操作系统你已经完成了。您不能在从返回之前生成异步线程,drawRect:并且期望能够通过返回到主线程来进行绘制,因为一旦您从drawRect:上下文返回就会被破坏。

执行此操作的常用方法是将信息缓存在单独的线程上,然后调用invalidateRect:您需要绘制的区域,让您的drawRect:方法除了快速绘制和退出之外什么都不做。

如果您想延迟加载缩略图,我建议将缩略图的副本存储在一个私有位置(可能使用 NSCache 并使用您的图像标识符作为键),然后如果图像在drawRect:调用时存在于缓存中,则绘制图像,否则绘制一个占位符并使用 GCD 将图像添加到队列以创建缩略图。在该调度队列调用内部:

  • 检索缩略图
  • 将其存储在缓存中
  • 调用invalidateRect包含图像的区域

如果您发现很难计算位置,或者您的缩略图非常快,您可以延迟 invalidateRect: 并在您的绘图例程结束时在最终的 dispatch_async 中调用它(但前提是您将缩略图排队等待恢复)。这将导致单个全区域重绘,而不是针对包含单个缩略图的每个区域进行多次重绘。

于 2012-05-26T12:53:03.567 回答