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
バインドされます。これにはそれぞれオブジェクトであるプロパティがあります。したがって、テーブルの行内のイメージビューはバインドされ、同じトランスフォーマーになります。NSArray
News
creator
User
objectValue.creator
これが機能しない理由についていくつかのアイデアはありますか?
編集:「プログラムによる」作品に関する私の声明を削除しました。私はそれが機能しているのを見ましたが、おそらく他の理由によるものでした。だから…user.picture
値を設定すると、KVO通知が観測オブジェクトに送信されません…KVOプロトコルを正しく処理していないと思い始めていますが、ガイドを読んでもエラーを理解できません。
最初の「ケース」(NSImageView
バインディング) では、バインドしたユーザー オブジェクトはラッパー内にあります。したがって、私が正しく理解している場合、ラッパーもユーザーオブジェクトに対して KVO に準拠している必要があります。しかし、私はそれだと思います:
@property (nonatomic, strong, readonly) User *user;
もちろん、User
オブジェクトはNSManagedObject
サブクラスです (ただし、私のコントローラーはNSMangedObjectContext
.. とは関係ありませんが、これは問題ではないと思います…</p>