1

私はRestKitから始めて、なんとかクエリを実行してTableViewControllerにロードしました。

クエリは、idTask、nameTask、および assignedUserId を返します。

ここまでは大丈夫、完璧に動作します。問題は、ユーザーの名前をその assignedUserID からロードしたいときに発生します (それは他の要求です)。

私は次のことを行います:

- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
    [self.refreshControl endRefreshing];
    NSLog(@"%d Tasks received", objects.count);
    self.resultsArray = objects;

    Task *task;
    for (int i=0; i<self.resultsArray.count; i++){
        task=(Task*) [self.resultsArray objectAtIndex:i];
        task.user= [[User alloc]init];
        [task.user getUserDetails:task.idUser];
    }
    [self.resultsTable reloadData];
}

ユーザーが自分のクラスを呼び出してデータをロードするタスクごとに、そのユーザーはクラスの作業でデータを利用できません。彼の属性は常に NULL です。

複数のオブジェクトをロードするにはどうすればよいですか?

Mi クラスのユーザーは次のようなものです: #import "User.h"

@implementation User


-(User *) getUserDetails:(NSNumber *)idUsuario{
    [self loadUsersAssigned:idUsuario];
    return self;
}

-(void) loadUsersAssigned:(NSNumber *)idUsuario
{
    NSString *urlGetUser;
    urlGetUser = [NSString stringWithFormat:@"MY URL", idUsuario,[[NSUserDefaults standardUserDefaults] objectForKey:@"userAccessToken"]];
    //Load objects from url
    RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[User class]];

    //Set relations (keys)
    [objectMapping mapKeyPath:@"id" toAttribute:@"idUser"];
    [objectMapping mapKeyPath:@"first_name" toAttribute:@"name"];
    [objectMapping mapKeyPath:@"last_name" toAttribute:@"lastName"];

    RKObjectManager* manager = [RKObjectManager sharedManager];

    [manager loadObjectsAtResourcePath:urlGetUser delegate:self block:^(RKObjectLoader* loader){
        loader.objectMapping = objectMapping;
        [loader setCachePolicy:RKRequestCachePolicyNone];
    }];
}

- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
    NSLog(@"Users recived: %d",objects.count);
    NSArray *result = objects;
    User *u = [result objectAtIndex:0];
    self.idUser=u.idUser;
    self.name=u.name;
    self.lastName=u.lastName;
}


- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error
{
    //    [self.refreshControl endRefreshing];
    //    NSLog(@"Error: %@", error.description);
}

@end

アップデート:

おっしゃるとおり、ブロックを使えばいいと思いますが、使ったことがないのでやり方がわかりません。

オブジェクトは正しいデータを返していますが、到着が遅すぎます。ログとコードを示します。

あなたが説明している方法でループを修正しました。それは次のようなものです:

int i=1;
for (Task *task in [self resultsArray]){
    NSLog(@"--- begin iteration %d ---",i);
    task.user= [[User alloc]init];
    task.user =[task.user getUserDetails:[task idUser]];
    NSLog(@"task inside objectLoader of Task id:%@ - name:%@ - lastname:%@",task.user.idUser,task.user.name,task.user.lastName);
    NSLog(@"--- end iteration %d ---",i);
    i++;
}

次に、ログに次のように表示されます。

2013-01-29 10:38:32.075 --- begin iteration 1 ---
2013-01-29 10:38:32.075 task inside objectLoader of Task id:(null) - name:(null) - lastname:(null)
2013-01-29 10:38:32.076 --- end iteration 1 ---
2013-01-29 10:38:32.076 --- begin iteration 2 ---
2013-01-29 10:38:32.077 task inside objectLoader of Task id:(null) - name:(null) - lastname:(null)
2013-01-29 10:38:32.078 --- end iteration 2 ---
2013-01-29 10:38:33.570 Users recived: 1
2013-01-29 10:38:33.570 Object loader of user: 522327,Xavi,Sanchez
2013-01-29 10:38:33.640 Users recived: 1
2013-01-29 10:38:33.640 Object loader of user: 522327,Xavi,Sanchez

ループが終了すると、ユーザー オブジェクトが読み込まれます。それ以前は、ユーザーのオブジェクトは null でした。ユーザーオブジェクトが読み込まれるまで待つには、ブロックなどを使用する必要があります。

4

1 に答える 1

0

非同期リクエスト

あなたは非同期リクエストを作成しており、同期的に動作することを期待しています.ここでは多くの概念が欠けています. 説明を簡単にすると、これは、要求されたオブジェクトをコードと同時に取得することは期待できないことを意味します。あなたが気づいたように、それは常にそれを追いかけます。リクエストを行ってから数秒後に、 objectLoader didLoadObjectsメソッドでオブジェクトを受け取ります。これらの秒は、マシンがインターネットに何かを要求して応答を得るのにかかる時間です。

単純な解決策は、リクエストから取得したオブジェクトで実行したいロジックを、ユーザーのobjectLoader didLoadObjectsに移動することです。しかし、あなたは物事を混ぜているので、それは非常に悪い考えです.

object-c でブロックを使用する方法について読んで、オブジェクトの結合を避けるためにオブジェクトを取得する方法を変更してください。RestKit でブロックを使用する方法を学ぶ必要があります。この質問を確認してください。役立つ場合があります。

ユーザー情報が取得できない

まず、サーバーが何かを返しているかどうかを確認する必要があると思います。そのため、URL が正しくないためにリクエストを送信している場合は破棄できます。

次のコードを追加して、ネットワークで何が起こっているかを確認します。これにより、ネットワーク ログが有効になります。

RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);

適切な応答が得られた場合は、マッピング プロセス後にそのデータがどのようにオブジェクトに変換されているかを確認します。

RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

これは何が間違っているのかを指摘する必要があります。

ログに何も記録されていない場合、問題はリクエストが実行されていないことです。あなたをさらに助けるために何を得ているのか教えてください。

複数のオブジェクトのロード

各要求は高価です。ここで、タスクを取得するために 1 つの要求を実行し、それらのタスクの各ユーザーに対して 1 つの要求を実行しています。N 件のタスクがある場合は、N+1 のリクエストを作成しています。それは効率的ではありません。すべてのタスクに同じユーザーがリンクされていると、さらに悪化します。

あなたがすべきことは、サービスを変更して(可能であれば)、インターフェースに必要なユーザー情報を追加し、ユーザー名を追加し、1 つの要求ですべてを取得することです。1 人のユーザーについてさらに詳細が必要な場合は、完全なユーザー情報を備えたサービスが必要になります。必要な場合に備えてリクエストを行いますが、常にではありません。

推奨事項

デリゲート/プロトコルの方法ではなく、ブロックを使用してリクエストを処理することをお勧めします。私の経験では、このケースでデリゲートを扱うのは常に頭痛の種であり、コードは読みやすくなります。

for の代わりに forin の方がきれいです

for サイクルの代わりに、次のことを試してください。

for (Task *task in [self resultArray]) {
    task.user = [[User alloc] init];
    [[task user] getUserDetails:[task idUser]];
}
于 2013-01-28T13:33:52.137 に答える