私は長い間これをいじろうとしてきましたが、最善のアプローチを見つけることができないようです. この一見単純なタスクを達成する方法については、さまざまな回答/意見があるように思われるため、混乱しています。
ActivityIndicatorController という再利用可能なクラスを作成したいと考えています。このコントローラーには、activateIndicator と activateIndicator の 2 つの主要なメソッドがあります。引数/プロパティとして UIView と、ラベルの NSString を取ります。アクティブ化すると、UIView でのユーザー操作がオフになり、四角形のサブビュー (アルファと角の丸いもの)、UIActivityIndicator コントロール、およびステータス テキスト用の UILabel が追加されます。これは、各ビュー コントローラーにカスタム UIActivityIndicatorView コードを用意したり、各 NIB に ActivityIndicator を設定したりする必要がないため、望ましい方法です。
私が根本的に抱えている問題は、ActivityIndicator を追加してアニメーション化するこのプロセスを開始する方法です。私が試したいくつかの方法では、新しいビューがまったく表示されません。他のものは機能しますが、ActivityIndicator はアニメーションしません。
activateIndicator メソッド内で [NSThread detachNewThreadSelector:@selector(startAnimating) toTarget:activityIndicator withObject:nil] を使用しようとしましたが、新しい UIView が表示されません。
呼び出し元のメソッドから [NSThread detachNewThreadSelector:@selector(activateIndicator) toTarget:activityIndicatorController withObject:nil] を使用しようとしましたが、これにより、新しい UIView の作成全体が別のスレッドに配置されます。
今質問に:
パート 1: すべての UI をメイン スレッドで処理する必要があることは理解していますが、それでよろしいですか?
パート 2: [NSThread detachThreadSelector] と NSOperation の違い/利点/欠点は何ですか?
パート 3: 次のことを行う方が良いですか?
(a) メイン スレッドへのコールバックを使用して、時間のかかる操作を新しいバックグラウンド スレッドに送信する、または
(b) UIActivityIndicatorView の startAnimating メソッドを別のスレッドに送信し、メイン スレッドで長いプロセスを実行します。
なぜ?
これが私の現在のコードです:
ActivityViewController クラス:
-(void)activateIndicator {
NSLog(@"activateIndicator called");
if (isActivated || !delegateView)
return;
NSLog(@"activateIndicator started");
[delegateView.view setUserInteractionEnabled:NO];
[delegateView.navigationController.view setUserInteractionEnabled:NO];
[delegateView.tabBarController.view setUserInteractionEnabled:NO];
float w = [[UIScreen mainScreen] bounds].size.width;
float h = [[UIScreen mainScreen] bounds].size.height;
NSLog(@"Width = %f\nHeight = %f", w, h);
if (!disabledView) {
disabledView = [[[UIView alloc] initWithFrame:CGRectMake((w - kNormalWidth) / 2.0, (h - kNormalHeight) / 2.0, kNormalWidth, kNormalHeight)] autorelease];
disabledView.center = [[[delegateView.view superview] superview] center];
[disabledView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.85]];
CALayer *layer = [disabledView layer];
NSLog(@"layer=%@",layer);
NSLog(@"delegate=%@",[layer delegate]);
layer.cornerRadius = 12.0f;
}
if (!activityIndicator) {
activityIndicator = [[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(kNormalWidth / 2, 10.0f, 40.0f, 40.0f)] autorelease];
[activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityIndicator.center = disabledView.center;
}
if (!activityLabel) {
activityLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10.0f, 100.0f, kNormalWidth - 20, 38)] autorelease];
activityLabel.text = labelText;
activityLabel.textAlignment = UITextAlignmentCenter;
activityLabel.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
activityLabel.textColor = [UIColor colorWithWhite:1.0f alpha:1.0f];
activityLabel.center = disabledView.center;
}
[[[delegateView.view superview] superview] addSubview:disabledView];
[[[delegateView.view superview] superview] addSubview:activityIndicator];
[[[delegateView.view superview] superview] addSubview:activityLabel];
[NSThread detachNewThreadSelector:@selector(startAnimating) toTarget:activityIndicator withObject:nil];
}
アプリ内の複数の場所からコードを呼び出す:
ActivityIndicatorController *aic = [[ActivityIndicatorController alloc] init];
aic.delegateView = self;
aic.labelText = @"Test...";
[aic activateIndicator];
//DO LENGTHY WORK ON MAIN THREAD
[aic deactivateIndicator];
[aic release], aic = nil;