iPhoneレシピ4:UIActionSheetにプログレスバーを表示する
ポイント
UIActionSheetの高さはタイトルの改行か、setNumberOfRowsメソッドで設定する。ただしsetNumberOfRowsはドキュメントには載っていないメソッド。
UIActionSheetはメインスレッドで表示しないと、ボタンが効かないっぽい。また、表示とその他の処理を同一スレッド内で行うと、処理終了までUIActionSheetが表示されない。
ソース
UIActionSheetの組み立て部分はこんな感じ。
- (void)viewDidLoad { [super viewDidLoad]; actionSheet = [[UIActionSheet alloc] initWithTitle:@"Please wait\n\n\n\n" delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel",nil) destructiveButtonTitle:nil otherButtonTitles:nil]; progressBar = [[UIProgressView alloc] initWithFrame:CGRectMake(30.0f, 40.0f, 240.0f, 90.0f)]; progressBar.progressViewStyle = UIProgressViewStyleDefault; progressBar.progress = 0.0f; [actionSheet addSubview:progressBar]; progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(30.0f, 50.0f, 240.0f, 20.0f)]; progressLabel.backgroundColor = [UIColor clearColor]; progressLabel.textColor = [UIColor whiteColor]; progressLabel.font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; [actionSheet addSubview:progressLabel]; }
表示と処理のスレッド分けはこんな感じ。
- (IBAction)start { cancelFlag = NO; // UIActionSheetはメインスレッドで表示しないとボタンが効かないっぽい。 [self showSheet]; [self performSelectorInBackground:@selector(doProcess) withObject:nil]; } - (void)showSheet { progressBar.progress = 0; progressLabel.text = NSLocalizedString(@"Processing...", nil); [actionSheet showInView:self.view]; } // 何かしらの処理 - (void)doProcess { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @try { for (int i=0; i<100; i++) { if (cancelFlag) return; // Background threadで動いている時はUIProgressViewをMainThreadで動かすこともできる。 // どちらで動かすべきかはよく分からない。 // [self performSelectorOnMainThread:@selector(progress:) withObject:[NSNumber numberWithFloat:0.01f] waitUntilDone:NO]; [self performSelectorInBackground:@selector(progress:) withObject:[NSNumber numberWithFloat:0.01f]]; [NSThread sleepForTimeInterval:0.1f]; } [actionSheet dismissWithClickedButtonIndex:-1 animated:YES]; } @finally { [pool release]; } } - (void)progress:(NSNumber *)amount { progressBar.progress += [amount floatValue]; NSLog(@"%f", progressBar.progress); } /////////////////////////////////////////////////////////////////// // UIActionSheetDelegate implements // - (void)actionSheet:(UIActionSheet *)sheet didDismissWithButtonIndex:(NSInteger)buttonIndex { if (buttonIndex == sheet.cancelButtonIndex) { cancelFlag = YES; } }