我有两个实体,一个叫做Post,另一个叫做User。发布<< ---->用户是核心数据中的关系。我使用NSFetchedResultsController获取核心数据堆栈中的所有Post记录,然后在UITableView中显示它们。每个单元格都有一个图像,该图像对应于User.profilePicture。
初始化时,我不从服务器下载配置文件图片,我只在它滚过该单元格时下载(延迟加载)。下载后,我将下载的图像保存到核心数据堆栈中相应的User.profilePicture中。
当我更新User实体时,是否有一种方法可以调用controllerDidChangeContent?我目前的理解是我的NSFetchedResultsController只能跟随Post实体,因为这是我最初设置它并且不能遍历和监视关系中的更新,是真的吗?
答案 0 :(得分:4)
可悲的是,我只知道这个问题的UGLY解决方案。
在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 Post元素有变化。
您可以找到其他信息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;
}
答案 1 :(得分:-2)
我认为这个问题可以在没有NSFetchedResultsController参与的情况下解决。
使用SDWebImage,SDWebImage可以异步加载来自远程服务器的图像,只需这样做:
[myImageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
使用KVO,向User实体添加观察者并相应地更新相应的图像视图。但是KVO的代码相当复杂,ReactiveCocoa可以简化它们:
[RACAble(user.profilePicture) subscribeNext:^(UIImage *image) {
[myImageView setImage:image];
}];