以编程方式更改主详细信息应用中的多个UI视图

时间:2013-07-07 19:56:26

标签: ios objective-c ipad uiimageview

为了正确地传达作者的意图而重新编写本问题

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

    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”)和一个他接下来要做的挑战(“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 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 if else if语句,如何更改颜色?当我选择其他玩家时,如何清除颜色?

2 个答案:

答案 0 :(得分: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个左右的ChallengeViews,并调用[currentView drawChallenge:currentChallenge]。

基本上,当添加新挑战时,您可以为其创建视图,并为视图指定挑战。当挑战视图由iOS呈现时,它会像drawChallenge方法中描述的那样绘制“它”的挑战。

如果您需要在模型 - 视图 - 控制器模式上使用入门,那么Apple文档的this section非常好。在这种情况下,您可以忽略Controller角色。

答案 1 :(得分: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作为值引用。