我有一个User
班级的模型。用户有一个picture
NSImage
属性(在 coredata 中设置可转换)。我要做的是在第一次访问时从服务器中检索图片。
第一个解决方案(可行但我不喜欢)是添加一个类别和另一个 NSImage 属性。UI 绑定到第二个属性。第一次访问它时,它会连接到服务器并检索图像。这个解决方案的问题是我必须向这个类传递对AFHTTPClient
我在 appdelegate 中创建和初始化的 httpclient(我使用 AFNetworking,所以)的引用。目前它是一个单例,但我不喜欢这个解决方案。
所以……这是我正在尝试的第二件事:我在AFHTTPClient
包装类中创建了以下方法
- (void)loadPictureForUser:(User*)user
imageLoadedCallback:(void(^)())callback
{
//if picture is already loaded do nothing
if (user.picture) return;
//if the request is already "ongoing" then do nothing
if ([self.imageLoadingRequests objectForKey:user.id]) return;
//We have to make a request
//set the placeholder while we wait for the image
#if TARGET_OS_IPHONE
user.picture = [UIImage imageNamed:@"UnknownUserPicture"];
#else
user.picture = [NSImage imageNamed:@"UnknownUserPicture"];
#endif
//make the request
NSDictionary *params = @{
@"id" : user.id,
@"size" : @(80),
@"count" : @(random() % 1000000)};
AFHTTPClient *httpClient = self.httpClient;
NSURLRequest *imageRequest = [httpClient requestWithMethod:@"GET"
path:ServerGetUserPictureURL
parameters:params];
__weak ConnectionManager *weakSelf = self;
AFImageRequestOperation *imageRequestOperation =
#if TARGET_OS_IPHONE
[AFImageRequestOperation imageRequestOperationWithRequest:imageRequest
imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
user.picture = image;
//in every case I have to remove the entry from the dictionary
[weakSelf.imageLoadingRequests removeObjectForKey:user.id];
BLOCK_SAFE_EXEC(callback);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
//in every case I have to remove the entry from the dictionary
[weakSelf.imageLoadingRequests removeObjectForKey:user.id];
}];
#else
[AFImageRequestOperation imageRequestOperationWithRequest:imageRequest
imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSImage *image) {
//save the picture in the user
user.picture = image;
user.picture.name = user.nickname;
//in every case I have to remove the entry from the dictionary
[weakSelf.imageLoadingRequests removeObjectForKey:user.id];
BLOCK_SAFE_EXEC(callback);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
//in every case I have to remove the entry from the dictionary
[weakSelf.imageLoadingRequests removeObjectForKey:user.id];
}];
#endif
[self.imageLoadingRequests setObject:imageRequestOperation forKey:user.id];
[httpClient enqueueHTTPRequestOperation:imageRequestOperation];
}
此方法设置一个占位符,直到它检索到正确的图片。此方法是从自定义调用的NSValueTransformer
- (id)transformedValue:(id)value
{
if (![value isKindOfClass:[User class]])
return nil;
User *user = value;
[self.connectionManager loadPictureForUser:value imageLoadedCallback:NULL];
return user.picture;
}
占位符设置正确(显然)。问题是当设置了正确的图片时,UI 没有更新。我认为这可能是我如何绑定属性的问题......</p>
我在两个不同的地方使用它:
- 一个简单的
NSImageView
..我将value
属性直接绑定到fileowner.connectionManger.user(fileowner是一个NSWindowController
子类,connectionmanager跟踪登录的用户)然后我在上面设置了转换器。 - 一个
NSTableView
。NSArrayController
绑定到类的包含NSArray
对象News
。每个都有一个属性creator
,它是一个User
对象。所以表中行内的图像视图绑定到objectValue.creator
同一个转换器。
关于为什么这不起作用的一些想法?
编辑:我删除了关于“以编程方式”工作的声明。我看到它起作用了,但也许是出于其他原因。所以……当我设置user.picture
值时,没有 KVO 通知发送到我的观察对象……我开始认为我没有正确处理 KVO 协议,但我阅读了指南,但仍然无法找出错误。
对于第一个“案例”(NSImageView
绑定),我绑定的用户对象位于包装器内。因此,如果我理解正确,包装器应该与用户对象的 KVO 兼容。但我认为是:
@property (nonatomic, strong, readonly) User *user;
当然,该User
对象是一个NSManagedObject
子类(但我的控制器与NSMangedObjectContext
.. 没有关系,但我认为这不是问题......</p>