パスワード入力欄をブルブルする

iOS用アプリでパスワード入力UIを作ってるのですが、無効なパスワードを入力した時のフィードバックをどうしようか考えて、Mac OSX Lionのログイン画面のように、パスワード入力フィールドが「イヤイヤ」って感じで左右に揺れる感じにしようと思いました。いっそこれくらいCocoaの標準メソッドとしてあってくれても良さそうなものでしたが、UITextfieldのリファレンスを見る限りはなさそうだったので自分で実装してみました。さして高度なことしてるワケでもないですし、あんまりエレガントなソースでないかも知れないですが晒しておきます。もっとこうすりゃいいんじゃね?的なコメントも歓迎。

2011.10.27追記:

s1tnkさんにアドバイスいただいて大幅な簡略化に成功したので、更新版を貼ります。

//パスワードが不適切だった場合に入力欄を揺らす
-(void)shakePasscodeField {

    [UIView setAnimationRepeatAutoreverses:TRUE]; //最初の位置に戻る
    [UIView animateWithDuration:.05
         animations:^(void) {
             passcode.center = CGPointMake(passcode.center.x – 10, passcode.center.y);
         }
         completion:^(BOOL finished) {
             [UIView animateWithDuration:.05 animations:^(void) {
                  passcode.center = CGPointMake(passcode.center.x + 10, passcode.center.y);                                             
                  }
                  completion:^(BOOL finished) {
                      [UIView animateWithDuration:.05 animations:^(void) {
                           passcode.center = CGPointMake(passcode.center.x – 10, passcode.center.y);
                           }
                           completion:^(BOOL finish) {
                               [UIView animateWithDuration:.05 animations:^(void) {
                                    passcode.center = CGPointMake(passcode.center.x + 10, passcode.center.y);
                                    }];
                           }];
                  }];
         }];

1メソッドで完結できたのでほとんど説明は不要だと思います。passcodeというのがテキスト欄の名前です。

旧バージョンとの違いは、

  • setAnimationRpeatAutoreversesの存在を教わり、左に行って戻る、右に行って戻るの2フェーズで表現できた
  • completion引数に次の処理をブロックで丸ごと角ことでアニメーションを連鎖記述できるようになった
  • 結果として2フェーズx2回を1つのメソッドに完結させ、状態変数を一切なくせた
  • durationは往復なので時間を倍の0.05にした

という辺りです。振動回数のカスタマイズはやりにくくなっちゃいましたが。

 

実際の動作はこんな感じ(IE9かiOSのSafari位しかインラインで再生できないかも)。

動画がインラインで再生されない人は、こちらからMP4をダウンロードして再生して下さい(44KB)。

■以下旧バージョン

前提として、.hファイル当たりで、

IBOutlet UITextField *passcode;
INT gakuburuCounter;
BOOL isFirstLoopForShakePasscodeField;

という3つのオブジェクト、変数を宣言してあるとします。

んで、.mファイルでメソッドを2つ。

//パスワードが不適切だった場合に入力欄を揺らす
-(void)shakePasscodeField {

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:.1];     
    [UIView setAnimationDidStopSelector:@selector(shakePasscodeFieldLoop)];
    switch (gakuburuCounter % 3) {
        case 0:
            //左へ動くフェーズ 
            [UIView setAnimationDuration:.025];     
            passcode.center = CGPointMake(passcode.center.x -10, passcode.center.y);
            break;
        case 1:
            //左位置から右へ動くフェーズ 
            [UIView setAnimationDuration:.05];     
            passcode.center = CGPointMake(passcode.center.x +20, passcode.center.y);
            break;
        case 2:
            //右位置から初期位置へ戻るフェーズ 
            [UIView setAnimationDuration:.025];     
            passcode.center = CGPointMake(pa
sscode.center.x -10, passcode.center.y);
            break;
        default: 
            break;
    }
    [UIView commitAnimations];
   
}

-(void)shakePasscodeFieldLoop { 
    if (isFirstLoopForShakePasscodeField == TRUE) {
        gakuburuCounter = -1;
        isFirstLoopForShakePasscodeField = FALSE;
    }

    if (gakuburuCounter < 5) {
        gakuburuCounter++;
        [self shakePasscodeField];
    }
}

こんな感じ。

#つーか、そろそろコードをカラーリングしてくれるライブラリを導入した方がいいんだろうなぁ…

パスワードを検証してNGだったら

isFirstLoopForShakePasscodeField = TRUE;
[self shakePasscodeFieldLoop]

って感じで呼びます。

簡単に補足しておくと、テキストフィールドが定位置から左に10ピクセル、右に20ピクセル、左に10ピクセルと移動するのを1つのセットとします。ただしこれを単純に連続して呼ぶと、前のアニメーションが終わらないうちに次が実行されてしまい、正しく移動してくれないので、1つのアニメーションが終わる度に次のステップのアニメーションを実行する仕組みが必要でした。そこでそれを管理するメタメソッド(そんな言葉あるのか?)としてshakePasscodeFieldLoopを作りました。isFirstLoopForShakePasscodeFieldフラグがTRUEの状態で呼ばれると、ループカウンタgakuburuCounterをリセット(ここでは-1)して、フラグをFALSEにします。そしてgakuburuCounterをカウントアップしながらshakePasscodeFieldを呼び出します。呼ばれたshakePasscodeFieldではgakuburuCounterを3で割った答えを使って順に3つの動作パターンを実行し、アニメーションが完了した後でshakePasscodeFieldLoopを呼びます。このルートで呼ばれたshakePasscodeFieldLoopはisFirstLoopForShakePasscodeFieldがFALSEなのでカウンターはリセットせず、カウントアップだけして再度isFirstLoopForShakePasscodeを呼びます。これで、gakuburuCounterが-1~5にカウントアップする過程で、各フェーズが順に2ループ実行されます。

カスタマイズですが、-10とか20ってのが移動ピクセル数です。左に10、右に20、左に10って感じで辻褄を合わせます。つまり、振幅を倍にするなら、-20、40、-20とかするワケです。

 

shakePasscodeFieldLoop内の5を8にするとブルブルが3回になります。以降3を足すと1セット増加です。

shakePasscodeField内のUIView setAnimationDurationの値がブルブルの速度です。case 1のところは移動距離が倍なので所用時間も倍にしておくのがポイントです。

Xcodeで幽霊.xibに困った時の覚え書き

Xcodeで開発をしていて、あるタイミングからInterface Builderから.xibファイルに対して行った変更がビルドに反映されなくなってしまいました。

  • Clean
  • Clean Build Folder (Option押しながらClean)
  • シミュレーター上のアプリを削除
  • Xcodeの再起動
  • OSの再起動

なども効果無し。挙げ句、Xcode上から当該.xibファイルを削除(他フォルダに移動)してもビルドしてくれやがります。Xcode上でもFinder上にも存在しないゴーストがどこかに残ってる!

結果として解決したのは、海外の掲示板stack overflowのこのエントリの一番下(記事執筆時)のコメント。よりによってusefulカウンタが0(笑)。そろそろσ(^^)もIDとって評価記入するようにしないとなぁ。

で、具体的にはXcodeのもってるキャッシュを削除。その場所は、

/Users/(ユーザ名)/Library/Developer/Xcode/DerivedData/

ここに今までビルドしたプロジェクト毎のフォルダがあるので、それを丸ごと削除。Lionだとユーザのホーム下のLibraryは不可視になってるので、ターミナルを使うが良いでしょう。

どうもここのキャッシュはXcode上で元ファイルが消されても消されずに使われてしまうっぽいです。では元々何故起きたかについてですが、多分、.xibをローカライズして、実体ファイルがen.lprojとja.lprojに移動/コピーされた時の参照が正しく書き換わらなかったっぽい気がしています。なんかやり方が悪かったんですかね?これによってXcode上では実体ファイルである各言語別のファイルを更新し続けたものの、ビルドには親フォルダにある(あった)ファイルのキャッシュが使われ続けてしまった、ということではないかと思っています。

同日追記:

@s1tnkさんより、Xcode4から同じことをする方法を教わりました。こっちの方が簡単そげ。この作業自体はエラーのハイライティングが壊れた時とかにもする一般的なものみたいです。特定プロジェクトがなんとなく調子悪いぜって時のお試し作業の1つとして覚えておくと良さそうです。

  1. Organizerを開く
  2. 目的のプロジェクトを選択する
  3. Delived Dataという見出しの右にある「Delete…」をクリック

 

delete_derivedData

dgKeyframe2Chapterをリリースしました

かなり前の「iOS向け高機能MP4自炊まとめ」というエントリで、Pegasys社のTMPGEncシリーズで書き出された.keyframeファイルを、mp4chap.exeでmp4ファイルに埋め込んで、iOS端末等でチャプターとして利用できる.chapters.txt形式に変換するツールを作った、と書いたところ、1年も経ったところで公開リクエストをいただいたので、公開しました。

こちらに置いておきます。

例によって自分用にサクッと作ったモノなので、あまり汎用性はないかも知れませんが。

また秒単位以下までキッチリ出力してほしいという要望があったので、v1.2では選択できるようにしてみました。もともと秒単位以下を切り捨ててた理由は、フレーム単位で指定してもmp4のようなフォーマットでは精密にジャンプできないことが多く、大抵少し前後してしまうことを鑑みて、例えばオープニングを飛ばした時に、少し本編の頭が欠けるよりはオープニングのお尻がちょろっと見える方がマシだろうと考え、フレーム単位は切り捨てをしていた、という経緯があります。が、まぁその辺りはお好みなのでなるべく厳密に計算した値を入れられるようにもしてみました。σ(^^)はMediaCoderでエンコすることが多いですが、今だとTMPGEnc Mastering Work 5でエンコすればKeyframeがきっちりIフレームとして扱われる気がするので、ドンピシャの方がいいのかも知れませんね。

ちょっと計算式がこれであってるか自信ないのでどなたかチェックしていただけると助かります。簡単には、.keyframeファイルの数値を29.97で割ると整数部分が秒単位になるので、それを取り除いた小数点以下の部分を使い、(特に指定してないですが多分)小数点以下4桁目を四捨五入して上位3桁を使用しているつもりです。

#そういう意味では「秒単位で丸める」というチェックボックスのラベルは不適切だなぁ(実際は切り捨て)。機会があれば直します。

なお、BDInfo.exeの「View Report…」等から取得できるBDMVのチャプター書式を.txt拡張子で保存したファイルをドロップした場合は、元々フレーム単位まできっちり出力してたみたいなので、こちらはそのままです。というか「秒単位で丸める」がONでも丸められません。手抜きですみません…

あと保存時にカチャっと確認音がしてたんですが、これもON/OFFできるようにと要望があったので対応しました。

 

ともあれ同好の士のお役に立てば幸いです。

iOSアプリ第二弾「おやゆびでお」がリリースされました

ブログでお知らせするのが遅くなりましたが、iOSアプリの第二弾、「おやゆびでお(英名:ThumbVideo)」がリリースされました。

以前からTwitterなどでは「動画関係である」ことを仄めかしていましたが、しかしてその実体は?

片手操作にこだわった動画再生アプリです。モバイルデバイスであるiPhone/iPod touchは片手で扱うことが多いですよね?例えば電車で片手はつり革につかまって、とか。またiPadもベッドやソファで寝モバする時に、自分のお腹の上に置いて片手で保持しつつ、もう片方の手はポテチつまんでる、とか。そうした片手持ち状態で動画を視聴するにあたって、画面幅一杯に水平表示されるスライダーは扱いやすいとは言えません。この不便さを解消するUIを備えた動画プレーヤーが「おやゆびでお」です。

具体的には、

  1. 画面上の好きな場所で左右フリックすることで指定秒数ジャンプします
  2. タイムスライダーは画面の左右端に垂直に表示されます
  3. 画面の好きな場所をダブルタップすると再生/一時停止ができます

どれも本体を横にして保持した状態でその手の親指だけで操作ができます。だから「おやゆびでお」なワケです。

さらに次バージョンでは、

  1. 画面上の好きな場所でグルグル円を描くと早送り、巻き戻しができる

というジョグダイヤル的な機能が追加されます(そろそろ審査出します)。フリックだと細かすぎるけどスライダーだと荒すぎる、という間のニーズを狙った機能です。実際にはMPEG4なのでビデオデッキについてたような本当の意味でのジョグダイヤル的なコマ単位操作は無理だし、ストリーミング再生の場合も考慮してリアルタイムでダイヤルの動きに追従して映像が移動するような仕様にはしませんでした。長押しするとカウンターが表示され、一周回す毎に“溜め”カウントされ指を離すと一気に移動する、という感じです。回す半径に応じて小さいと1分、大きく回すと5分単位で溜めが増減します。

 

電子書籍ビューワーは機能はどれも似たり寄ったりながら操作性で差別化されているのに対し、、動画プレーヤーに関しては実際の再生中の部分は標準コンポーネントを使ったものばかり。そこに一石を投じられればと思い作成しました。電子書籍同様に自炊コンテンツを用意するようなマニアなユーザでないと利用場面もないかと思いますが、逆にだからこそこだわったUIにしたいなと。このブログを購読してくださってりような方なら共感してくださる方、色々こだわりを持ってる方も多いんじゃないでしょうか?是非ご要望、アイデアなどお寄せいただければと思います。

 

画面写真も含めアプリ詳細ページはこちら

AppStoreの製品ページは下のバナーをクリックして下さい。

おやゆびでお (ThumbVideo) - 道具眼 (do-gugan)

 

 

P.S.

第一弾「AccentViewer」は諸般の事情でなかったことになりました。ご購入下さった方にはご迷惑をおかけして申し訳ありませんでしたm(..)m。

ようやくiOSアプリ第一弾AccentViewer公開

最初にdefault languageの設定を間違え、Appleに修正依頼をするも梨の礫。結局半年分のライセンスを諦めて別アカウントを取り直してみるも契約情報が既に存在するというエラーが出て有料アプリ設定ができず、これまたサポートに出して返事がない。結局日本のサポートに電話したところ、iTunes Connect設定は日本の部署では触れないが、要求は翻訳して本国に伝えるというのでまたまた待つことしばし。なんだかんだで二ヶ月ほど遅れてしまいましたが先ほどようやく公開にこぎつけました。

一本目はAccentViewerという文字通り日本語のアクセントを調べるアプリ。Twitterでとある現役の声優さんから頼まれて作ってみました。元々大辞林には見出し語の脇に小さくアクセント位置を示す数字が記載されてるんですが、これを視覚的に見やすい形で変換して表示するものです。Yahoo!辞書が大辞林のデータでひけるのでそれを利用してます。声優とかアナウンサーとか特定業種の人や日本語を学んでいる外国人の人などニッチ向けなんであんまり売り上げは期待してないです。むしろ知ってる声優さんがブログやTwitterで触れたりしてくれたら密かにニヤニヤして満足って感じ(笑)。

AccentViewer - 道具眼 (do-gugan)

 

また道具眼謹製iOSアプリの専用サイトを開設しました。

http://do-gugan.com/iosapps/

またTwitterアカウントも専用のものを作りました。アプリ情報だけチェックしたいという方はこちらをフォローしていただくと良いかと思います。

http://twitter.com/do_gugan_apps

 

第二弾はもう少し一般向け(でもないか?)な動画プレーヤーアプリになると思います。一応完成してるので後は紹介文や画面写真などを用意してなるべく間を置かず公開したいと思います。

どうぞよろしくお願いします。