0

为了正确传达作者的意图,此问题已重新编写

我有一个 MasterDetail 应用程序,它最终将成为一种通过固定数量的“挑战”(确切地说是 60 个)跟踪“玩家”数量的方法。每个玩家的挑战都是相同的,而每个玩家在个人挑战中的状态可能会有所不同。所有关于玩家的数据都存储在 Postgres 数据库中,然后使用 LeftViewController 中的 JSONModel 获取。我从数据库中正确获取了所有数据,并且已成功将其放入 NSMutableDictionary。Dictionary 中的数据如下所示(这是一位玩家):

    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"
        );
    },

正如你所看到的,玩家有一些挑战“完成”(“done”),一些他不需要做(“pass”),一个他正在做(“currentChallenge”)和一个他要完成的挑战接下来会做(“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) 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 方法中描述的那样。

如果您需要模型-视图-控制器模式的入门知识, Apple 文档的这一部分非常好。在这种情况下,您可以忽略 Controller 角色。

于 2013-07-07T20:44:25.717 回答
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 回答