使用新对象更新UIview

时间:2012-05-05 11:59:05

标签: ios xcode view refresh reload

我有一个方法makeButtons(在这里发布),它删除了屏幕上的所有按钮并再次添加它们。这在viewDidLoad和viewDidAppear中工作正常。我正在从Web服务访问信息,它告诉我我需要一个新按钮。当我从该方法调用[self makebuttons]时,没有任何事情发生,直到我使用我的NavigationController向前和向后移动,迫使viewDidAppear再次完成工作。我的问题是为什么?我做的完全一样,除非它不是从viewDidAppear调用的,而是来自doneGettingInformation。

- (void) viewDidAppear:(bool) animated {
    [self makebuttons]; // Works great!
}

- (void) doneGettingInformation : (ASIFormDataRequest *) request {
    NSString *response = [request responseString];
    [[self.temp.userInfo objectForKey:@"spillider"] addObject:response];
    [self makebuttons]; // This gets called, but nothing changes in the view itself.
}

- (void) makeButtons {
    NSLog(@"kjort");
    int newAntall = [[self.temp.userInfo objectForKey:@"spillider"] count];
    for (UIButton * button in gameButtons) {
        NSString *tag = [NSString stringWithFormat:@"%i",button.tag];
        [button removeFromSuperview];
        if ([webviews objectForKey:tag]) {
            [[webviews objectForKey:tag] removeFromSuperview];
            [webviews removeObjectForKey:tag];
        }
    }
    [gameButtons removeAllObjects];
    scroller.contentSize = CGSizeMake(320, 480);
    if (newAntall > 3) {
        CGSize scrollContent = self.scroller.contentSize;
        scrollContent.height = scrollContent.height+((newAntall-3)*BUTTON_HEIGTH);
        self.scroller.contentSize = scrollContent;
    }
    int y = 163;
    self.nyttSpillKnapp.frame = CGRectMake(BUTTON_X, y, BUTTON_WIDTH, 65);
    for (int i=0; i<newAntall; i++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button setBackgroundImage:[UIImage imageNamed:@"knapp_midt"] forState:UIControlStateNormal];
        [button setBackgroundImage:[UIImage imageNamed:@"knapp_midt"] forState:UIControlStateHighlighted];
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button.titleLabel setFont:[UIFont systemFontOfSize:15]];
        button.frame = CGRectMake(BUTTON_X, y, BUTTON_WIDTH, BUTTON_HEIGTH);
        button.enabled = YES;
        UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self
                                                                                    action:@selector(deleteButton:)];
        swipe.direction = UISwipeGestureRecognizerDirectionRight;
        [button addGestureRecognizer:swipe];
        button.tag = [[[self.temp.userInfo objectForKey:@"spillider"] objectAtIndex:i] intValue];
        NSString * tittel = [NSString stringWithFormat:@"spill %@",[[self.temp.userInfo objectForKey:@"spillider"] objectAtIndex:i]];
        [button setTitle:tittel forState:UIControlStateNormal];
        UIButton *subButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        subButton.transform = CGAffineTransformMakeRotation(M_PI_2);
        subButton.tag = i;
        CGRect subframe = CGRectMake(230, 5, subButton.frame.size.width, subButton.frame.size.height);
        subButton.frame = subframe;
        CGRect myframe = self.nyttSpillKnapp.frame;
        myframe.origin.y = myframe.origin.y+BUTTON_HEIGTH;
        self.nyttSpillKnapp.frame = myframe;
        [subButton addTarget:self action:@selector(clickGameButton:) forControlEvents:UIControlEventTouchUpInside];
        [button addSubview:subButton];
        [gameButtons addObject:button];
        [self.scroller addSubview:button];
        y += BUTTON_HEIGTH;
    }
}

总而言之,它只有在我来回更改viewcontrollers导致viewWillAppear被调用时才有效。那是为什么?

我为我糟糕的方法感到抱歉。

由于

1 个答案:

答案 0 :(得分:1)

如果您在初始视图显示过程或布局更改之外更改视图的内容,则您有责任调用setNeedsDisplay并通知运行循环它需要重新绘制。

系统会要求视图最初绘制内容或在布局更改期间绘制内容,这就是为什么它作为首次显示视图的过程的一部分。在初始过程中,将调用viewWill / DidAppear委托。

来自UIView class reference

  

查看绘图周期

     

根据需要查看绘图。首次显示视图时   或者当全部或部分由于布局变化而变得可见时,   系统要求视图绘制其内容。对于包含的视图   使用UIKit或Core Graphics的自定义内容,系统调用   view的drawRect:方法。你实现这个方法是   负责将视图的内容绘制到当前图形中   上下文,由系统在调用之前自动设置   这种方法。这会创建一个静态的视觉表示   视图的内容随后可以显示在屏幕上。

     

当视图的实际内容发生变化时,它就是您的   有责任通知系统您的视图需要   重绘。您可以通过调用视图的setNeedsDisplay或来执行此操作   setNeedsDisplayInRect:视图的方法。这些方法让   系统知道它应该在下一次绘图期间更新视图   周期。因为它等到下一个绘图周期才更新   在view中,您可以在多个视图上调用这些方法来更新它们   同时。

编辑:

此外,确保在后台线程上不调用获取图像。您无法在后台线程上编辑视图。如果是,你可以在bg线程上准备所有数据,然后在主线程上调用makeButtons(performSelectorOnMainThread或使用块。

请参阅GCD, Threads, Program Flow and UI Updating