2

Userクラスを持つモデルがあります。ユーザーにはpicture NSImage属性があります (coredata で変換可能に設定されています)。私がやりたいことは、最初にアクセスしたときにサーバーから画像を取得することです。

最初の解決策 (うまくいきますが、私は好きではありません) は、カテゴリと別の NSImage プロパティを追加することです。UI は、この 2 番目のプロパティにバインドされています。初めてアクセスすると、サーバーに接続して画像を取得します。このソリューションの問題は、appdelegate でAFHTTPClient作成および初期化する httpclient (AFNetworking を使用しているため) への参照をこのクラスに渡す必要があることです。現在はシングルトンですが、このソリューションは好きではありません。

だから…これは私がしようとしている2番目のことです:私は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>

私は2つの異なる場所でそれを使用します:

  • シンプルなNSImageView..value属性をfileowner.connectionManger.userに直接バインドし(fileownerはNSWindowControllerサブクラスであり、connectionmanagerはログインしているユーザーを追跡します)、トランスフォーマーを設定します。
  • NSTableView。_ は、クラス の包含オブジェクトにNSArrayControllerバインドされます。これにはそれぞれオブジェクトであるプロパティがあります。したがって、テーブルの行内のイメージビューはバインドされ、同じトランスフォーマーになります。NSArrayNewscreatorUserobjectValue.creator

これが機能しない理由についていくつかのアイデアはありますか?

編集:「プログラムによる」作品に関する私の声明を削除しました。私はそれが機能しているのを見ましたが、おそらく他の理由によるものでした。だから…user.picture値を設定すると、KVO通知が観測オブジェクトに送信されません…KVOプロトコルを正しく処理していないと思い始めていますが、ガイドを読んでもエラーを理解できません。

最初の「ケース」(NSImageViewバインディング) では、バインドしたユーザー オブジェクトはラッパー内にあります。したがって、私が正しく理解している場合、ラッパーもユーザーオブジェクトに対して KVO に準拠している必要があります。しかし、私はそれだと思います:

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

もちろん、UserオブジェクトはNSManagedObjectサブクラスです (ただし、私のコントローラーはNSMangedObjectContext.. とは関係ありませんが、これは問題ではないと思います…</p>

4

0 に答える 0