4

我有两个实体,一个叫Post,一个叫User。 Post < < ---->用户是核心数据中的关系。我正在使用NSFetchedResultsController来获取我的核心数据栈中的所有Post记录,然后在UITableView中显示它们。每个单元格都有一个图像,并且该图像对应于User.profilePicture。NSFetchedResultsController UITableView的多个实体

初始化时,我不从服务器上下载配置文件图片,我只在滚动通过该单元格时才下载(延迟加载)。一旦我下载它,我将下载的图像保存到核心数据堆栈中对应的User.profilePicture中。

当我更新用户实体时,是否有方法可以调用controllerDidChangeContent?我目前的理解是,我的NSFetchedResultsController只能跟随Post实体,因为这是我最初设置的,不能遍历和监视关系中的更新,这是真的吗?

回答

4

可悲的是我只知道对这个问题的丑陋的解决方案。

在你User .m文件实现setProfilePicture:这样的:

//NOT TESTED IN A MULTITHREADED ENV 
- (void) setProfilePicture:(NSData *)data 
{ 
    [self willChangeValueForKey:@"profilePicture"]; 
    [self setPrimitiveValue:data forKey:@"profilePicture"]; 
    [self.posts enumerateObjectsUsingBlock:^(Post* p, BOOL *stop) { 
     [p willChangeValueForKey:@"user"]; 
     [p didChangeValueForKey:@"user"]; 
    }]; 
    [self didChangeValueForKey:@"profilePicture"]; 
} 

这将通知FRC,邮政元素都有变化。

您可能会发现更多的信息here

编辑:

要提取的访问,你可以添加到您的User .M数据:

//UNTESTED 
+ (void) mergeToMain:(NSNotification*)notification 
{ 
    AppDelegate* appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 
    [appDel.managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
                withObject:notification 
               waitUntilDone:YES]; 
} 

- (NSData*)_profilePicture 
{ 
    return [self primitiveValueForKey:@"profilePicture"]; 
} 

- (NSData*) profilePicture 
{ 
    [self willAccessValueForKey:@"profilePicture"]; 
    NSData* picData = [self primitiveValueForKey:@"profilePicture"]; 
    if (!name) { 
     __block NSManagedObjectID* objectID = self.objectID; 
     //This solves the multiple downloads per item by using a single queue 
     //for all profile pictures download. 
     //There are more concurrent ways to accomplish that 
     dispatch_async(downloadSerialQueue, ^{ //define some serial queue for assuring you down download multiple times the same object 
      NSError* error = nil; 
      AppDelegate* appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 
      NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init]; 
      [context setPersistentStoreCoordinator:appDel.persistentStoreCoordinator]; 
      [context setUndoManager:nil]; 
      User* user = (User*)[context existingObjectWithID:objectID error:&error]; 
      if (user && [user _profilePicture] == nil) { 
       NSData *data = //[method to retrieve data from server]; 
       if (data) { 
        if (user) { 
         user.profilePicture = data; 
        } else { 
         NSLog(@"ERROR:: error fetching user: %@",error); 
         return; 
        } 
        [[NSNotificationCenter defaultCenter] addObserver:[self class] selector:@selector(mergeToMain:) name:NSManagedObjectContextDidSaveNotification object:context]; 
        [context save:&error]; 
        [[NSNotificationCenter defaultCenter] removeObserver:[self class] name:NSManagedObjectContextDidSaveNotification object:context]; 
       }      
      } 
     }); 
    } 
    [self didAccessValueForKey:@"profilePicture"]; 
    return picData; 
} 
+0

嗯,我将不得不尝试这个,它似乎并不丑陋......在多线程环境下,那些KVO消息需要在m ain线程? – inks2002 2013-04-26 19:06:50

+0

我相信它可以工作,但还没有测试过(稍后会这样做) – 2013-04-26 19:08:53

+0

已测试,并且在合并其他线程的更改时进行更新。 – 2013-04-26 19:18:50

-2

我认为这个问题可以解决,而不涉及NSFetchedResultsController。

  1. 使用SDWebImage,SDWebImage可以异步加载从远程服务器的图像,只是这样做:

    [myImageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] 
           placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; 
    
  2. 使用KVO,一观察者添加到用户实体和相应的更新相应的图像视图。但是对于志愿的代码是相当复杂的,ReactiveCocoa可以简化他们:

    [RACAble(user.profilePicture) subscribeNext:^(UIImage *image) { 
        [myImageView setImage:image]; 
    }]; 
    
相关问题