0

この質問は、著者の意図を適切に伝えるために書き直されました

最終的に一定量の「チャレンジ」(正確には60)を通じて「プレーヤー」の量を追跡する方法になるMasterDetailアプリがあります。チャレンジはすべてのプレイヤーで同じですが、個々のチャレンジでの各プレ​​イヤーのステータスは異なる場合があります。プレイヤーに関するすべてのデータは Postgres データベースに保存され、LeftViewController の JSONModel を使用して取得されます。DB からすべてのデータを正しく取得しており、NSMutableDictionary に正常に配置しました。Dictionary のデータは次のようになります (これは 1 人のプレーヤーです)。

    player =     (
            {
        id = 9;
        name = "Arthur Dent";
        currentChallenge = "Cooking";
        timeStarted = "04 Jul 2013 1:08 PM";
        challengesDone = (
                            {
                challengeName = "Flying";
                timeCompleted = "04 Jul 2013 12:08 PM";
            }
        );
        nextChallenge = "Swimming";
        freePass =             (
            Running,
            "Climbing"
        );
    },

ご覧のように、プレイヤーには「完了」(「完了」) されたいくつかのチャレンジ、実行する必要のないチャレンジ (「パス」)、実行中のチャレンジ (「currentChallenge」)、およびプレイヤーが実行する 1 つのチャレンジがあります。次に実行します (「nextChallenge」)。プレイヤーが陥る可能性のあるこれらの状態ごとに、RightViewController にある「課題」を色分けして、何が起こっているかを一目で理解できるようにしたいと考えています。NSMutableDictionary にあるデータによって決定されるプレーヤーのステータスに基づいて、さまざまな色を点灯させる「チャレンジ」が必要です。

NSDictionary のデータから配列を作成することで、次のようにして色を変更できます。

if ([freePassArray containsObject:@"challenge three name"])
{
    UIImage *image = [UIImage imageNamed:@"status_pass.png"]; //status_pass.png is my color
    [challengeThreeImageView setImage:image];
}

しかし、このようにすると、240 個の if ステートメントと else if ステートメントを記述して、60 のチャレンジすべてで考えられるすべてのステータスをカバーする必要があります。

次のようにデータを渡すため、配列には選択したプレーヤーのデータのみが含まれます。

* LeftViewController.m * didSelectRowAtIndexPath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    //Re-fetch the feed from the Postgres Database when a user selects an entry

    [JSONHTTPClient getJSONFromURLWithString:@"http://myurl" completion:^(NSDictionary *json, JSONModelError *err) {
    NSError* error = nil;
    _feed = [[PostgresFeed alloc] initWithDictionary:json error:&error];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:nil userInfo:[[json objectForKey:@"preclear"] objectAtIndex:indexPath.row]];

}];

Player *selectedPlayer = [_players objectAtIndex:indexPath.row];

if (_delegate) 
    {
    [_delegate selectedPlayer:selectedPlayer];
    }
}

そのため、一度にすべてのプレイヤーの画像が設定されることはありませんが、別のプレイヤーが選択された後も画像はクリアされません。

240 の if ステートメントと else if ステートメントを書かずに色を変更するにはどうすればよいですか? また、別のプレーヤーを選択したときに色をクリアするにはどうすればよいですか?

4

2 に答える 2

0

50 個すべての画像があり、どのチャレンジがどの画像に対応するかを知っていると仮定すると、実際のチャレンジ画像の上にステータス画像を配置します。

- (void)setChallengesDone:(NSArray*)doneAr next:(NSArray*)nextAr current:(NSArray*)currentAr andPass:(NSArray*)passAr
{
    // remove additions from the previous selected player
    UIView *prevAdditionsView = [self.view viewWithTag:122333];
    while (prevAdditionsView != nil)
    {
        [prevAdditionsView removeFromSuperview];
        prevAdditionsView = [self.view viewWithTag:122333];
    }

    for (int i=0; i<[doneAr count]; i++)
    {
        [self addChallengeImageAdditionWithImage:@"status_done" forChallenge:[doneAr objectAtIndex:i]];
    }

    for (int i=0; i<[nextAr count]; i++)
    {
        [self addChallengeImageAdditionWithImage:@"status_next" forChallenge:[nextAr objectAtIndex:i]];
    }

    for (int i=0; i<[currentAr count]; i++)
    {
        [self addChallengeImageAdditionWithImage:@"status_current" forChallenge:[currentAr objectAtIndex:i]];
    }

    for (int i=0; i<[passAr count]; i++)
    {
        [self addChallengeImageAdditionWithImage:@"status_free" forChallenge:[passAr objectAtIndex:i]];
    }
}

- (void)addChallengeImageAdditionWithImage:(NSString*)image forChallenge:(NSString*)challengeTitle
{
    UIImageView *challengeImage = [challenges objectForKey:challengeTitle];

    CGRect frame = challengeImage.frame;
    UIImageView *statusImg = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:image]] autorelease];
    [statusImg setFrame:frame];
    [statusImg setAlpha:0.5]; // optionally add some transparency
    [statusImg setTag:122333];
    [self.view addSubview:statusImg];
    [self.view bringSubviewToFront:challengeImage]; // bring challenge image to front
}

チャレンジ タイトルを UIImageViews にマップする最も簡単な方法は、チャレンジ タイトルをキーとして NSDictionary を維持し、対応する UIImageViews への参照を値として維持することです。

于 2013-07-07T20:50:58.007 に答える
0

これは、モデル/ビューの概念の優れた例です。

  • 各チャレンジは、必要なすべての情報 (チャレンジ名、ステータス、タイムスタンプなど) を含むモデルです。
  • 50 個のビューのそれぞれが、チャレンジをレンダリングする方法を知っている「チャレンジ ビュー」です。
  • ステータスデータはモデルにあります。ステータス画像が表示されます。

例:

-(void) drawChallenge: (Challenge*) challenge
{
    // Draw challenge name as text
    switch ([challenge status])
    {
        case done: // draw "done" image
        case next: // draw "next" image
    }
}

アイデアは、チャレンジ自体がそれがどのようにレンダリングされるかを認識すべきではなく、ビューがチャレンジに含まれるものを認識すべきではないということです。ビューはそれを描画する責任があります。

これは、UIView の ChallengeView サブクラスにパックできます。次に、50 ほどの ChallengeView を作成し、[currentView drawChallenge: currentChallenge] を呼び出します。

基本的に、新しい課題が追加されると、そのためのビューを作成し、そのビューに課題へのポインターを与えます。チャレンジ ビューが iOS によってレンダリングされると、drawChallenge メソッドで説明したように、「その」チャレンジが描画されます。

Model-View-Controller パターンの入門書が必要な場合は、Apple ドキュメントのこのセクションが非常に役立ちます。この状況では、コントローラーの役割を無視できます。

于 2013-07-07T20:44:25.717 に答える