1

次の問題があります。ユーザーがボタンを押したときにダウンロードしてほしい。このダウンロード中は、他のボタンを非表示にします(ダウンロードしたファイルを開くため、更新がまだ完了していないときに誰もファイルを開こうとしないようにします)。このプロセス中にこれらのボタンを非表示にすることは可能ですか?

だから私がこれまでに試し、経験したこと:

  • ボタンの変更は、常に最後に取得します(更新が行われるため、不要になった場合)。

私は次のことを試しました(擬似コード):

-(void)updatingprogress
{
    buttona.hidden=TRUE;
}

-(void)updatingfinished
{
    buttona.hidden=FALSE;
}

updateFiles()
{
[self updatingprogress]
... make downloads...
[self updatingfinished]
}

したがって、ロギングを使用すると、必要なときに機能を利用できるようになりますが、「updatingprogress」中にボタンの変更は行われません。この問題を解決する方法はありますか?よろしくお願いします!

4

2 に答える 2

4

一般的な問題は、バックグラウンドスレッドでUI要素を更新しようとしていることです。updateFilesメソッドが別のスレッドで発生している場合、ボタンが適切に非表示になっていない可能性があります。メインスレッドにメソッドをディスパッチするには、NSOperationQueueAPIまたはAPIのいずれかを使用できGCDます。

NSOperationQueue:

[[NSOperationQueue mainQueue] addBlockOperation:^ {
    buttona.hidden = YES;
}];

GCD:

dispatch_async(dispatch_get_main_queue(), ^ {
    buttona.hidden = YES;
});

これらのAPIはどちらも同じことをします。私は通常、可能な限り最高の抽象化を使用しようとするので、この場合はNSOperationQueueメソッドを使用します

于 2012-06-01T01:05:55.037 に答える
1

もう1つの可能性は、メインスレッドですべての作業を行っているが、原則として、実行ループにドロップダウンするまでUIKitの変更が有効にならないという事実を考慮に入れていないことです。

背景のロジックは、部分的な変更を表示したくないというものです。たとえば、次のように記述した場合です。

// okay, set to success
label.textColor = [UIColor greenColor];  // was previously red
label.text = @"Success";                 // previously said 'Failure'

明示的に望まないのは、「Failure」という単語が緑色で表示されてから、「Success」に変わることです。2つの変更をアトミックに発生させる必要があります。Appleは、UIKitの更新をまとめてバッチ処理し、スケジュールされたメソッドの外部でそれらを実行することによってこれを実現します。

したがって、UIの変更を行い、作業を行ってからUIの変更を元に戻す関数がメインスレッドにある場合、実行ループに戻ることなく、変更が表示されることはありません。

最も迅速な解決策は次のとおりです。

- (void)updateFiles
{
    [self updatingProgress];
    [self performSelector:@selector(doFileUpdate) withObject:nil afterDelay:0.0];

    // what does the above achieve? It schedules doFileUpdate on the runloop, to
    // occur as soon as possible, but doesn't branch into it now. So when this
    // method returns UIKit will update your display
}

- (void)doFileUpdate
{
    /* heavy lifting here */
    [self updatingFinished];
}
于 2012-06-01T01:33:57.123 に答える