今請け負っている仕事でViewを画像変換して保存するという仕様があるのだが、CALayerを3d transformしていて、いざrenderInContextで画像に変換しようとしたら、transformが反映されませんでした。ドキュメント見たら「layers that use 3D transforms are not rendered」なんて書かれてて、あと二日くらいでOpenGLで書き直しか?と非常にあせった。
で、3Dな変換は行っていなかったので、かわりにaffineTransformを使ってみたら無事変換できた。
Evernoteを利用して暗記学習を行うためのiPhoneアプリ「Everword – Evernote暗記カード 」を公開しました。
Evernoteのノートブックを登録して、ノートブックにあるノートをカード形式で表示して暗記学習をするためのアプリです。
Evernoteのノートは複雑な書式が使えるので、単純なノートの英単語の暗記から複雑なノートが必要な専門分野の知識の記憶まで可能です。Evernoteに情報を集約することになるので、情報の活用の幅が広がります。
私は英語の書籍を読む時に、分からない単語をEvernoteに入れていって、辞書アプリから単語の意味をコピーしてノートを作り、それをこのEverwordで学習しています。
また、習熟度別で3日後7日後など出題間隔が開くので、効率的な学習が出来ます。
無料ですので、ぜひ試しにダウンロードしてみてください。
無料ではノートブックの登録が一つに制限され、広告が表示されるという制約があります。アプリ内課金で250円支払っていただくと、ノートブックの登録制限と広告の表示が解除されます。複数のノートブックを使った方が、学習内容をよりマネージメントしやすくなります。
簡単に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でビューコントローラーを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の標準アプリが充実して、サードパーティつぶしだ、いや開発者ががんばればいいんだ、というような記事が散見されますが、私はそのようなレベルの話ではないと考えています。
私の知人にiPhone4ユーザがいます。その人のPCはネットに繋がっていません。App Storeからアプリもほとんどダウンロードしていないようです。iTunesすら知らないのです。
今後はiPhoneとiPadだけしか使わないという人も現れるでしょう。(既に存在するかな)
そのような人がiPhoneを使うことを考えると、自然と標準アプリの充実やiCloudに行き着くと思うのです。
私は、AppleがiOS5はそのような「ライトユーザ」に向けで開発したものではないかと考えています。ある人の言ですが「新しい携帯としてスマホを選ぶ」という状況になりつつあり、iPhoneもAndroidも同じような状況ではないでしょうか。
AppleはiOS5でサードパーティに「ライトユーザ」という新しい顧客を連れてきてくれます。標準アプリの充実は決してApple vs サードパーティではないのです。そして、今後はこれまで以上に「ライトユーザ」を意識した開発やマーケティングが必要になるから、みんながんばってね♡ by Apple、というのがiOS5がサードパーティにとって意味するところではないでしょうか。
Tacticon – Twitter/mixiアイコンを連絡先の写真に設定 + グループと連絡先の管理 を公開しました。
mixiにも対応しました。mixiのマイミクシィとiPhoneの連絡先を関連付けて、マイミクの画像やURLを連絡先に付けることができます。関連付けるので、画像が偏光された時には、再読み込みを行うことができます。
その他にTwitterのAPIの仕様が変更されたのでそれへの対応や、バグの修正を行いました。
バグ報告・要望・質問などがありましたら
・私のTwitterアカウント@rizumita
・このページへのコメント
・このサイトのお問い合わせフォーム
にメッセージを投稿ください。
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の場合はジェスチャにも反応しないので、トグル動作にはならなかった。
iPhoneでARマーカーを検知する動画をYouTubeで公開してみました。
YouTubeにあげること自体が初めてでドキドキ。
あんまりうまく撮影できてないのがかこわるいですが。
OpenCV使ってます。C++インターフェース使ってます。
マーカーの横に表示される数字は、マーカーの中の図形コードの数値です。図形コードの横のブロックでマーカーの方向を検知しています。
描画スクリーンサイズは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);