2

我有一个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跟踪登录的用户)然后我在上面设置了转换器。
  • 一个NSTableViewNSArrayController绑定到类的包含NSArray对象News。每个都有一个属性creator,它是一个User对象。所以表中行内的图像视图绑定到objectValue.creator同一个转换器。

关于为什么这不起作用的一些想法?

编辑:我删除了关于“以编程方式”工作的声明。我看到它起作用了,但也许是出于其他原因。所以……当我设置user.picture值时,没有 KVO 通知发送到我的观察对象……我开始认为我没有正确处理 KVO 协议,但我阅读了指南,但仍然无法找出错误。

对于第一个“案例”(NSImageView绑定),我绑定的用户对象位于包装器内。因此,如果我理解正确,包装器应该与用户对象的 KVO 兼容。但我认为是:

@property (nonatomic, strong, readonly) User *user;

当然,该User对象是一个NSManagedObject子类(但我的控制器与NSMangedObjectContext.. 没有关系,但我认为这不是问题......</p>

4

0 回答 0