在后台加载Facebook图像以保存到主线程上的核心数据

在后台加载Facebook图像以保存到主线程上的核心数据,facebook,image,core-data,grand-central-dispatch,Facebook,Image,Core Data,Grand Central Dispatch,我正在加载Facebook图片。我正在尝试使用下面的代码返回一个图像,以便使用核心数据将其保存到“Friend”对象的记录中。它不起作用了。。什么也不归还。有没有办法在后台加载数据,然后在主队列上创建图像并返回它?我需要在主队列上创建图像,因为我想使用我的应用程序代理的托管对象上下文将其保存到我的对象 + (UIImage *)imageForObject:(NSString *)objectID { NSString *url = [[NSString alloc] initWith

我正在加载Facebook图片。我正在尝试使用下面的代码返回一个图像,以便使用核心数据将其保存到“Friend”对象的记录中。它不起作用了。。什么也不归还。有没有办法在后台加载数据,然后在主队列上创建图像并返回它?我需要在主队列上创建图像,因为我想使用我的应用程序代理的托管对象上下文将其保存到我的对象

+ (UIImage *)imageForObject:(NSString *)objectID {

    NSString *url = [[NSString alloc] initWithFormat:@"https://graph.facebook.com/%@/picture?width=%d&height=%d",objectID,IMAGE_MAXWIDTH,IMAGE_MAXHEIGHT];
    __block UIImage *image;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];

        dispatch_async(dispatch_get_main_queue(), ^{

            image = [[UIImage alloc] initWithData:data];
        });
    });
    return image;
 }

当然,可以在后台加载图像,但不是这样。此方法的设计目的是,它不可能不返回nil。调用
dispatch\u async
时,它会立即返回并异步完成其工作。这就是为什么它的名字中有“async”。您的代码到达
返回图像在加载图像之前

不过,你的思路是对的。通常的方法是在后台工作完成后将其分派回主队列。但是,这样做时,像您这样的方法不可能返回图像。如果它这样做了,主队列将不得不等待图像加载,这就违背了在后台队列上运行的全部目的

你应该做的是:

  • dispatch\u async
    返回到主队列中,对图像执行任何需要执行的操作—在屏幕上显示图像,或将图像写入文件,或对图像执行任何需要执行的操作
  • 使您的方法返回
    void
    ,因为它不能将图像直接返回给调用者。或者,如果愿意,使其返回
    BOOL
    ,以指示图像加载是否已启动。但是它不能返回
    UIImage
    ,除非您让主队列等待映像——正如我提到的,这破坏了使用后台队列的全部目的

  • 谢谢汤姆,这是一个很好的回答。实际上,我有一个活动指示器在有目的地运行,因为我正在导入,可以让用户等待,因为他们可以看到他们正在等待。我会在后台做,但我不知道如何在后台成功保存。我只在整个应用程序中使用app delegate托管对象上下文,我知道我必须改变这一点。但我找不到一个在后台保存的好的可靠例子,除了一篇关于CIMGF的文章基本上指向使用魔法记录。每个人的做法似乎都不一样。不过我有一个问题-我发现如果传入正确的参数,我可以将映像保存在dispatch\u async(dispatch\u get\u main\u queue)中。您能否确认,如果我确实在那里创建并设置了映像,那么它将在我的主managedObjectContext(应用程序代理)中创建,并且在保存时不会出现问题?即使您认为可以让用户等待,但您真的真的不想在主队列上执行此操作。当下载发生时,您的UI将完全没有响应,使您的应用程序看起来好像崩溃了。后台队列的常用方法是使用多个托管对象上下文。也可以调度回主队列进行保存。更好的方法是在主运行中心上使用队列限制和
    performBlock
    performBlockAndWait
    。将用户界面阻塞任何可感知的时间长度都是非常糟糕的用户体验。例如,用户可能认为应用程序崩溃了。最好在后台下载时显示占位符图像,然后在准备好后更新UI。另外,为了您自己的利益,请查看队列限制、
    performBlock
    performBlock和wait
    。听起来不错,只是永远不要阻塞主队列超过绝对必要的时间。