TestFlight SDKを利用する

簡単にAdhocアプリを配布できるTestFlightからSDKがリリースされました。

  • セッション
  • クラッシュリポート
  • アプリ内での質問
  • チェックポイント
  • リモートロギング
  • アプリ内アップデート

といった機能があるようです。

早速組み込んでみたいと思います。

SDKのページからSDKをダウンロードして解凍します。

libTestFlight.aとTestFlight.hをXcodeプロジェクトに追加します。TestFlight.hを利用するファイルでimportするのですが、簡単に行うにはprojectname_Prefix.pchファイルの#ifdef __OBJC__セクションに#import “TestFlight.h”を記述します。プリプロセッサマクロで#ifdef ADHOCのように分岐するといいと思います。

http://testflightapp.com/dashboard/team/にアクセスしてeditをクリックしてチームトークンを取得します。取得したら
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[TestFlight takeOff:@”チームトークン”];
}
と記述します。チームトークンのところは書き換えてください。

結果はすべてビルドページで閲覧できます。

クラッシュリポートを有効にするにはビルドセッティングでDeployment Post Processing,Strip Debug Symbols During Copy,Strip Linked ProductをNoに設定します。アプリがクラッシュするとビルドページに表示され、スタックとレースなどを確認することができます。

チェックポイントを設定するには[TestFlight passCheckpoint:@”CHECKPOINT_NAME”];とします。チェックポイントを通過したデバイスの割合をビルドページで確認できます。

フィードバックを行えるビューを表示するには[TestFlight openFeedbackView];とします。フィードバックが送信されるとビルドページで確認して、返信することができます。

UINavigationControllerのアニメーションをカスタマイズする方法

UINavigationControllerでビューコントローラーをpush/popするときのアニメーションはスライドです。このアニメーションをカスタマイズしてみます。

ここではフェードを行ってみます。

まずはpushです。

- (IBAction)push {
    SubViewController *subViewController = [[[SubViewController alloc] initWithNibName:nil bundle:nil] autorelease];
    subViewController.view.frame = self.view.bounds;
    subViewController.view.alpha = 0.0;
    [self.view addSubview:subViewController.view];
 
    [UIView transitionWithView:subViewController.view duration:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void) {
        subViewController.view.alpha = 1.0;
    } completion:^(BOOL finished) {
        [self.navigationController pushViewController:subViewController animated:NO];
    }];
}

pushする対象はSubViewControllerです。現在のビューと同じサイズに設定して、透明にして、現在のビューにaddSubviewします。
アニメーションですが、alphaを1.0にして不透明にします。アニメーションが完了したらpushViewController:animated:でpushを行います。animatedにはNOを指定して、デフォルトのスライドアニメーションを行わないようにします。

次にpopです。

- (IBAction)pop {
    NSArray *viewControllers = [self.navigationController viewControllers];
    NSUInteger previousIndex = [viewControllers count] - 2;
    UIViewController *previousViewController = [viewControllers objectAtIndex:previousIndex];
    previousViewController.view.alpha = 0.0;
    [self.view addSubview:previousViewController.view];
 
    [UIView transitionWithView:previousViewController.view duration:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void) {
        previousViewController.view.alpha = 1.0;
    } completion:^(BOOL finished) {
        [self.navigationController popViewControllerAnimated:NO];
    }];
}

viewControllers から、pop後に表示される前のビューコントローラーを取得します。viewControllers配列の後ろから2番目に入っています。このコントローラーのビューのalphaを0.0に設定して透明にして、現在のコントローラーのビューに載せます。
アニメーションも同様にalphaを1.0に設定して、不透明にします。アニメーションが終了したらpopViewControllerAnimated:でpopします。これもNOを指定してデフォルトアニメーションを行わないようにします。

このように、UINavigationControllerでのフェードアニメーションは、push/popはどちらも、これから表示するビューを上に載せて、透明から不透明にアニメーションを行い、アニメーションが終了したタイミングでpush/popを行うことになります。

iOS5はサードパーティにとってどのような意味があるか

iOS5の標準アプリが充実して、サードパーティつぶしだ、いや開発者ががんばればいいんだ、というような記事が散見されますが、私はそのようなレベルの話ではないと考えています。

私の知人にiPhone4ユーザがいます。その人のPCはネットに繋がっていません。App Storeからアプリもほとんどダウンロードしていないようです。iTunesすら知らないのです。

今後はiPhoneとiPadだけしか使わないという人も現れるでしょう。(既に存在するかな)

そのような人がiPhoneを使うことを考えると、自然と標準アプリの充実やiCloudに行き着くと思うのです。

私は、AppleがiOS5はそのような「ライトユーザ」に向けで開発したものではないかと考えています。ある人の言ですが「新しい携帯としてスマホを選ぶ」という状況になりつつあり、iPhoneもAndroidも同じような状況ではないでしょうか。

AppleはiOS5でサードパーティに「ライトユーザ」という新しい顧客を連れてきてくれます。標準アプリの充実は決してApple vs サードパーティではないのです。そして、今後はこれまで以上に「ライトユーザ」を意識した開発やマーケティングが必要になるから、みんながんばってね♡ by Apple、というのがiOS5がサードパーティにとって意味するところではないでしょうか。

UIButtonのハイライトを持続する方法

UIButtonは標準動作ではタップするとハイライト(青くなる、もしくは画像を設定している場合は黒っぽくなる)した後に元の状態に戻る。

これをハイライトしたままにするには以下のように一瞬時間を置いて、ハイライトを設定し、enabledをオフにする。

- (IBAction)buttonTapped:(id)sender
{
    // senderはUIButtonとする
    [self performSelector:@selector(highlightButton:) withObject:sender afterDelay:0.0];
}
 
- (void)highlightButton:(UIButton *)button
{
    button.highlighted = YES;
    button.enabled = NO;
}

もしくは

- (IBAction)buttonTapped:(id)sender
{
    UIButton *button = (UIButton *)sender;
    [[NSOperationQueue mainQueue] performSelector:@selector(addOperationWithBlock:)
                                       withObject:[[^{
                                           button.highlighted = YES;
                                           button.enabled = NO;
                                       } copy] autorelease]
                                       afterDelay:0.0];
}

この方法ではボタンのタッチには反応しなくなるのでトグル動作は出来ない。ハイライトを消してタッチに反応するようにするには、highlighted=NO/enabled=YESを設定する。

また、トグル動作が可能かUITapGestureRecognizerを設定してみたが、やはりenabledがNOの場合はジェスチャにも反応しないので、トグル動作にはならなかった。

iOSにおけるCoreGraphicsによるオフスクリーンでの線分の描画例

描画スクリーンサイズは480×640で設定している。

以下の例では原点は左上になる。

UIGraphicsBeginImageContext(CGSizeMake(480, 640));
CGContextRef context = UIGraphicsGetCurrentContext();
 
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 3);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context);
 
CGImageRef imageRef = CGBitmapContextCreateImage(context);
self.view.layer.contents = (id)imageRef;
 
CGImageRelease(imageRef);
 
UIGraphicsEndImageContext();

以下の例では原点は左下になる。

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, 480, 640, 8, 0, colorSpace, kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
 
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 3);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context);
 
CGImageRef imageRef = CGBitmapContextCreateImage(context);
self.view.layer.contents = (id)imageRef;
 
CGImageRelease(imageRef);
CGContextRelease(context);

原点の移動は以下のように行う。これにより原点を左下から左上に変更できる。

CGContextTranslateCTM(context, 0, 640);
CGContextScaleCTM(context, 1.0, -1.0);

インストールしたiOS Firmwareの保存場所

iTunesのアップデートでインストールしたiOS Firmwareの保存場所は、Macでは~/Library/iTunesにあるiPad Software UpdatesフォルダやiPhone Software Updatesフォルダで、各々のイメージファイルがそのフォルダに入っている。

過去のバージョンが必要な場合はそこから取得できるかもしれない。iPadのVer3.2系イメージが欲しかったので、iPad Software Updatesフォルダを確認したら入っていた。

Windowsでは
C:\Documents and Settings\Account\Application Data\Apple Computer\iTunes\
らしい。未確認。

もし手元になければiPod, iPhone and iPad Firmware Downloadから取得できるらしいが信頼性は不明。

iOSで自動的にロックしないように設定する方法

iOSではユーザが設定した時間が経過すると自動的にロックされてスリープに入ります。これを自動的にロックされないようにする方法。

[UIApplication sharedApplication].idleTimerDisabled = YES;

これをロックされるように戻すには逆にNOを設定します。

私はFTPサーバを起動してファイルをiOSアプリに転送している時に設定。ゲームアプリでは良く使うのかな。

MPMoviePlayerControllerで戻る・進むボタンが機能しない場合の対処法

先日MPMoviePlayerControllerでローカルファイルを再生するコードを書いたのですが、戻る・進むボタンが正常に機能しませんでした。

具体的には

  • 再生後すぐに戻るボタンをタップすると動画再生が停止する
  • 進むボタンをタップすると動画再生が停止する
  • 少し再生した後に戻るボタンをタップするとはじめから再生される(正常に動作)

という状況でした。

検索しても答えは見つからず、Twitterで質問してみましたが、この現象を解決する回答はありませんでした。(が、今後役に立つであろう事を教えてもらえました。ありがとうございました。)

再度Stack Overflowで検索したところやっと解決方法を見つけました。

To fix back/forward (or previous/next) buttons you should do the following:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerPlaybackStateDidChange:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];

– (void) moviePlayerPlaybackStateDidChange: (NSNotification *) notification {
if (moviePlayer.playbackState == MPMoviePlaybackStateStopped) {
[moviePlayer setContentURL:[moviePlayer contentURL]];
[moviePlayer play];
}
}

[From MPMoviePlayerController problems on iPad – Stack Overflow]

これが答えでした。つまりPlaybackStateが変更された時に、playbackStateがMPMoviePlaybackStateStoppedだったらコンテンツURLを再設定して再生するというコードです。

これって、わざわざこのようなコードを入れないといけないのは少し変です。バグなのでしょうか?それともドキュメントのどこかに書いてあることなのでしょうか?

iPadの偏光方向について疑問あり

先日、信州大で「自然のからくり」という展示をやっていて、見学してきました。

その中で、偏光を使った展示があって、iMacに偏光板を付けて、角度によって柄の色が見える見えないってやってたんですね。で、斜めだったら見えるんだったかな。これはMacのディスプレイの偏光が斜め方向だからなんです。

で、展示担当の堅物そうだけど美人なおねぇさんの説明によると、人間の目は斜めの偏光には鈍感で、縦の偏光に良く反応するらしいです。で、縦だと汚い色に見えたりするんで、Macの斜めの偏光は色をきれいに見せてくれるらしいです。

実はMacの偏光が斜めだということは以前から知ってました。なぜかというと、いつもサングラスをしてパソコンに向かってるんですが、そのサングラス、偏光機能があるんです。

そこで疑問が。iPadは縦(横?)の偏光なんです。斜めでは無い。じゃぁiPadはMacより色が汚く見えることがあるのでしょうか?iPadだけでなく、使っているCinema Displayも縦ですね。どうなんでしょう。それになぜMacとiPadは偏光方向が違うのでしょう?詳しい人いたらコメントください。

それから、iPadが斜め偏光でないので、偏光サングラスしてるとポートレートでは全く画面が見えないんです。iPadなんとかして欲しいです。いや、偏光機能の無いサングラス欲しいです。