iOSアプリでローディング表示といえば、SVProgressHUDだと思います。
Googleで調べれば、解説サイト様も数多くあり、導入も比較的簡単です。
超簡単!iOSでたった数行でかっこいいローディング表示 – SVProgressHUD
ただ私の場合は、導入まではすぐにできましたが、その後でちょっとつまずいてしまいました。
今回はその内容をご紹介します。
なお、非常に初歩的なTipsだと思いますので、そこはご勘弁を。。。
写真を保存する時に表示が一瞬で消える。なぜ?
私は主にカメラアプリを作っているので、SVProgressHUDはカメラの保存時に使おうと考えていました。
具体的に言うと、アプリ内のSAVEボタンを押して、UIActivityViewControllerを使った保存の画面が出てくるまでの間です。
そして、私が最初に実装したのはSAVEボタンを押した際に呼び出されるメソッド内でした。
//Save用メソッド - (void)savePhoto { //ローディング開始 [SVProgressHUD showWithStatus:@"Wait..." maskType:SVProgressHUDMaskTypeGradient]; //保存用イメージを取得 // UIActivityViewController UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:@[screenImage] applicationActivities:activities]; // show [self presentViewController:activityView animated:YES completion:nil]; //ローディング終了 [SVProgressHUD dismiss]; }
「さあ、実機で試してみよう!」
「あれ?ローディングが一瞬で消える。なんで?」
予想外(私の中では。)の展開にちょっと戸惑いました。
ローディング表示はメソッド終了後に描画される
諦めようかなと、一瞬思いました。
ですが、私のカメラアプリの場合、カメラの保存に1秒くらい時間がかかります。
そのままですと、かるくフリーズ状態なので、Appleのレビューが通らない可能性が大です。
それは嫌だ。
そこで、いろいろと試してみました。
すると、どうやら処理の順番はどうあれ、SVProgressHUDのローディング表示はメソッド終了後に画面描画がされるらしいことがわかりました。
(技術的な検証はしていません。あくまで私はそう捉えたという話です。)
ということは、同じメソッド内でSVProgressHUDの開始と終了を記述した場合はどうなるか。
メソッド終了後に表示と表示終了が一瞬で行われる事になります。
今の現象とつじつまが合います。
あとは、解決策を考えるのみ。
Viewのタッチイベントにローディング処理を記述する。
その後の試行錯誤の末、私は以下の方法で解決しました。
1.Saveメソッドの呼び出しをボタンからではなく、Viewにする。
2.VIewのタッチイベント、touchesBeganにSVProgressHUDの開始を記述。
3.touchesEndedにSVProgressHUDの終了を記述。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; NSLog( @"%d",touch.view.tag ); switch (touch.view.tag) { case 1: // タグが1のビュー _retakeImageView.image = [UIImage imageNamed:@"home_button_2.png" ]; break; case 2: // タグが2のビュー _clearClipImageVIew.image = [UIImage imageNamed:@"cancel_button_2.png" ]; break; case 3: // タグが3のビュー _clipImageVIew.image = [UIImage imageNamed:@"add_button_2.png" ]; break; case 4: //Saveボタン押下時 // ローディング開始 [SVProgressHUD showWithStatus:@"Wait..." maskType:SVProgressHUDMaskTypeGradient]; // タグが4のビュー _saveImageVIew.image = [UIImage imageNamed:@"save_button_2.png" ]; break; default: break; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; NSLog( @"%d",touch.view.tag ); switch (touch.view.tag) { case 1: // タグが1のビュー [self selectModeRetake]; _retakeImageView.image = [UIImage imageNamed:@"home_button_1.png" ]; break; case 2: // タグが2のビュー [self delClip]; _clearClipImageVIew.image = [UIImage imageNamed:@"cancel_button_1.png" ]; break; case 3: // タグが3のビュー [self clipPhoto]; _clipImageVIew.image = [UIImage imageNamed:@"add_button_1.png" ]; break; case 4: // タグが4のビュー [self savePhoto]; _saveImageVIew.image = [UIImage imageNamed:@"save_button_1.png" ]; [SVProgressHUD dismiss]; break; default: break; } }
Snowflakeのソースをほぼそのままのせました。
Viewのタッチイベントについては、前の記事を参照して下さい。
touchesBegan
SnowflakeのSaveボタンがタッチされた場合だけ、SVProgressHUDの開始処理を記述しています。
それと、ボタンの画像もちょっと光ったような画像に差し替えています。
touchesEnded
各ボタンに対応したメソッドを呼び出しています。
そして、光らせたボタン画像を元に戻します。
Saveボタンの場合は、さらにSVProgressHUDの終了処理を記述しています。
いかがでしょうか。
これが正しいやり方かは正直わかりませんが、参考になれば。
コメント