0

画面内のすべてのボタンを削除して再度追加するメソッドmakeButtons(ここに投稿)があります。これは、viewDidLoadおよびviewDidAppearで正常に機能します。新しいボタンが必要だと言っているWebサービスから情報にアクセスしています。そのメソッドから[selfmakebuttons]を呼び出しているとき、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;
    }
}

要約すると、viewControllerを前後に変更してviewWillAppearが呼び出される場合にのみ機能します。何故ですか?

面倒な方法でごめんなさい。

ありがとう

4

1 に答える 1

1

最初のビュー表示プロセスまたはレイアウト変更以外でビューのコンテンツを変更した場合は、setNeedsDisplayを呼び出して、再描画が必要であることを実行ループに通知する必要があります。

システムは、最初に、またはレイアウトの変更中にそのコンテンツを描画するようにビューに要求します。そのため、最初にビューを表示するプロセスの一部として機能します。その最初のプロセス中に、viewWill/DidAppearデリゲートが呼び出されます。

UIViewクラスリファレンスから:

ビュー描画サイクル

ビューの描画は、必要に応じて行われます。ビューが最初に表示されたとき、またはレイアウトの変更によってビューの全部または一部が表示されたときに、システムはビューにその内容を描画するように要求します。UIKitまたはCoreGraphicsを使用するカスタムコンテンツを含むビューの場合、システムはビューのdrawRect:メソッドを呼び出します。このメソッドの実装は、ビューのコンテンツを現在のグラフィックスコンテキストに描画する役割を果たします。現在のグラフィックスコンテキストは、このメソッドを呼び出す前にシステムによって自動的に設定されます。これにより、ビューのコンテンツの静的な視覚的表現が作成され、画面に表示できます。

ビューの実際のコンテンツが変更された場合、ビューを再描画する必要があることをシステムに通知するのはユーザーの責任です。これを行うには、ビューのsetNeedsDisplayまたはsetNeedsDisplayInRect:メソッドを呼び出します。これらのメソッドは、次の描画サイクル中にビューを更新する必要があることをシステムに通知します。ビューを更新するために次の描画サイクルまで待機するため、複数のビューでこれらのメソッドを呼び出して、同時に更新することができます。

編集:

また、画像の取得が完了したことがバックグラウンドスレッドで呼び出されていないことを確認してください。バックグラウンドスレッドでビューを編集することはできません。その場合は、bgスレッドですべてのデータを準備できますが、メインスレッドでmakeButtonsを呼び出します(performSelectorOnMainThreadまたはブロックを使用します)。

GCD、スレッド、プログラムフロー、UIの更新を参照してください

于 2012-05-05T12:25:07.683 に答える