-
-
-
忙しい人のためのgmail活用術紹介します。IT詳しくない人でもできますよ。
2012年05月07日 投稿
-
-
-
-
スマートフォンの次を行く?!Windowsが動くガラケーF-07Cを買ってみた
2011年10月09日 投稿
-
-
-
-
RapidSSLを使うとAndroidで証明書エラーが出た場合
2011年07月07日 投稿
-
Tag Archives: Objective-C
Core Dataで管理されているオブジェクトを、UITableViewでの順序入れ替えに対応させる方法例
【前提条件】 あらかじめ、対象のManagedObjectに「position」というプロパティを作っておきます。 UITableViewの中身はNSFetchedResultsControllerで管理しておきます。 NSFetchedResultsControllerに渡すFetchRequestに、「position」でソートするようSortDescriptorを設定しておきます。 // Edit the sort key as appropriate. NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@”position” ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; セルが移動された際、以下のようなコードでpositionの値を書き換えることで、入れ替えが実現できました。 クラス名は、対象にするモデルクラスに書き換えてください。 // Override to support rearranging the table view. – (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath … Continue reading
[Xcode 4] テストケースで、外部のデータファイルを使う
Mac / iOSのテストケースを書いていて、外部のデータファイル(XML等)をテストケースから参照したい場合があると思います。 実際のアプリケーションの場合、Targetに登録されたファイルがバンドル内に存在するため、 NSString* path = [[NSBundle mainBundle] pathForResource:@”example” ofType:@”xml”]; NSData* data = [NSData dataWithContentsOfFile:path]; とすることで、データファイルの中身を取得可能ですが、 テストケースの場合そもそもバンドルが存在しないため、NSBundleからはパスが取れません。 フルパス指定するという方法もありますが、他の環境で動かなくなるため現実的ではありません。 そこで、相対指定をするわけですが、 相対指定をするためには、カレントパスが一体どこかを知る必要があります。 ぱっと探したところ、載ってるページがすぐには見つからなかったため、ログを出して調べてみました。 以下のコードで、カレントパスがわかります。 NSLog(@”Current Directory:%@”, [[NSFileManager defaultManager] currentDirectoryPath]); 結果、テストの実行時のカレントパスは、プロジェクトファイル(.xcodeproj)が存在するディレクトリであることがわかりました。 そのため以下のように、プロジェクトファイルが存在するディレクトリを基準として、相対パスでファイルを指定することで、 外部ファイルのデータを取得できました。 この際、「dataWithContentOfFile」で直接相対パスを入れると相対パスを展開してくれないため、 一旦NSURLを生成して、「dataWithContentsOfURL」を使うこともポイントです。 NSURL* URL = [NSURL fileURLWithPath:@”./AppTests/example.xml”]; NSData* data … Continue reading
Cocoa / Carbon間でキャストできるオブジェクト
NSStringからCFStringRef、NSURLからCFURLRefなどは、キャストするだけで変換できますが、 NSRunLoopからCFRunLoopRef、NSImageからCGImageRefなどは、キャストするだけでは変換できません。 キャストするだけで変換できるオブジェクトの一覧が載っているドキュメントが、 非常にわかりにくい場所ですが以下のページにあります。 Carbon-Cocoa Integration Guide (Legacy): Interchangeable Data Types Legacy登録されていて、検索などで出なくなっていますが、今でも使えます。 新しいドキュメントにも載せて欲しい。。
Undefined symbols: “_objc_msgSendSuper2″ に遭遇したら
iOSアプリ開発中、静的ライブラリのリンク・アンリンクを繰り返していたところ、 Undefined symbols: “_objc_msgSendSuper2″ , referenced from:… というエラーで、アプリをビルドできなくなる現象に遭遇しました。 このエラーは、libobjc.dylibが見つからず、Objective-Cの内部関数が見つからないことで起きているということまではすぐわかったのですが、 なぜlibobjc.dylibが急に見つからなくなったのか気づくまで少し時間がかかりました。 どうやら、静的ライブラリのリンク・アンリンクを繰り返していると、 希に、Library Search Pathsから、SDK標準のフレームワークフォルダ 「$(SDKROOT)/Developer/Library/Frameworks」 が除外されてしまうことがあるようです。(Xcode 4.0.2のバグ?) Target設定のBuild Settings設定のLibrary Search Pathsに、 「$(SDKROOT)/Developer/Library/Frameworks」 を再度追加してやることで、エラーは出なくなりました。
Objective-Cの静的ライブラリ内のカテゴリを使う
iOSアプリにおいて、静的ライブラリの中で実装されているカテゴリのメソッドを呼ぼうとすると、 「unrecognized selector sent to instance 〜」のエラーが出る場合があります。 忘れがちなのですが、静的ライブラリ内で実装されているカテゴリを呼ぶ場合は、 アプリのTargetの「Build Settings」の「Other Linker Flags」に、「-all_load」を追加してやる必要があります。 これを忘れると、カテゴリ内のメソッドを参照することができず、「unrecognized 〜」のエラーが発生します。 Technical Q&A QA1490によると、リンカのバグが原因のようです。
iPadでは、ステータスバーは半透明にできない
iPhone / iPad Universalアプリで、ステータスバーを半透明にしようとしたところ、iPadのみ半透明にできませんでした。 ログをよく見ると、 UIStatusBarStyleBlackTranslucent is not available on this device. というエラーが。 ドキュメントにはそれらしい記述が見つからなかったのですが、 どうやらiPad端末はUIStatusBarStyleBlackTranslucentに未対応のようです。 ただ、動画や画像などを見せる画面を作る場合、数秒後にステータスバーを隠すため、 その時に画面ぴったりになるよう、ステータスバーの裏側にもコンテンツを表示したいと思い、 とりあえず、viewWillAppear:とviewDidAppear:で次のようなフックを入れて回避しました。 – (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES]; } else { [[UIApplication … Continue reading
iPhone スレッドに注意
iPhoneでNSThreadのスレッドを使う際にうっかりミスった点をメモしておきます。 割と常識のようですが、特にUIImageViewのほうはエラーも出ないので初めてだと焦りますね;; autoreleaseに注意 何も考えずにスレッド用の関数内でautoreleaseが呼ばれると、 *** NSAutoReleaseNoPool(): Object 0x********* of class NSConreteData autoreleased with no pool in place …. といった感じのエラーが出てしまいます。 お決まりパターンとして、スレッドの最初で NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; しておいて、スレッド終了時に [pool drain] すればとりあえず問題なさそうです。 別スレッドからUIImageViewのimageを更新しても、表示されない 別スレッドで imageView.image = [UIImage imageNamed:@"Hoge.png"]; のような処理を実行しても、表示されません。 UIImageViewのimageを設定して表示する処理は、メインスレッドでないとダメみたいです。 メインスレッドで実行するには、実行する処理を関数にまとめた上、 [delegate performSelectorOnMainThread:@selector(theProcess:) … Continue reading
iPhone用 超手抜きUDPサーバ
先日のiPhone性能検証で作ったソースの一部として、超手抜きUDPサーバのコードを載せておきます。 CFSocketが思ったよりも使いにくいので、BSDソケットほとんど生です・・・ /** * 手抜きUDPサーバ */ #import <netinet/in.h> #import <Foundation/Foundation.h> @interface MyUdpConnection : NSObject { id delegate; } – (id)initWithDelegate:(id)_delegate; //receiveData:(NSData*)data を実装すること – (void)bind; – (void)bindThread; @end /** * 手抜きUDPサーバ実装部 */ @implementation MyUdpConnection // 初期化 – (id)initWithDelegate:(id)_delegate { delegate = … Continue reading
iPhoneのNSURLConnection性能限界テスト
iPhoneやiPod Touchは、ネットワークの性能がそれほど高くないため、NSURLConnectionでたくさんコネクションを張ったりすると目に見えて遅延します。 以下のような実験をやってみました。 iPhone SDKで、以下の2種類のテストアプリを作りました。 なお、機材の都合上iPhoneではなくiPod Touchを使っています。 【A】 タイマーで0.05秒ごとにHTTPリクエストを送信し、レスポンスとして受け取った画像を表示する。 サーバでは、リクエストを受け取るたびに0~9の数字画像を順番に返す。 【B】 UDPで接続を待ち、画像データを受け取ったら表示する。 サーバでは、iPhoneに向かって0.05秒ごとに0~9の数字画像を順番にUDPで送信する。 サーバは、十分に高性能なマシンを、有線LANで接続しました。 MacBook ProやiPod Touch実機は、同じ無線LAN (IEEE802.11g) を使っています。 【結果】 Aのアプリ(MacBook Pro上のシミュレータ) Aのアプリ(iPod Touch 実機) Bのアプリ(iPod Touch実機) このように、HTTPを使う場合、シミュレータではスムーズに動くものの、実機ではかなりカクカクです。 実機でも、HTTPを使わずにUDPにしてしまえば、十分スムーズになることが分かります。 今回使った画像は各2KB程度のPNG画像ですが、50KB程度のJPG画像を使っても結果はほとんど変わらなかったため、帯域よりもコネクションの数が大きなウェイトを占めているようです。 どの程度性能が出るか大まかに分かれば良かったので、原因などの細かい検証は今回は行いません。 使ったソースコードなどは後日このブログに載せておこうかと思います。
iPhoneで画面を横にする
iPhoneで画面を横にしたいときは、ViewControllerで – (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationLandscapeRight); } のようにオーバーライドします。 (この関数はViewControllerを作る際にXCodeが生成するので、コメントアウトして少し書き換えるだけ) しかし、Tab Bar Applicationを使っている場合、この方式だと、全部のViewControllerのうち、最も厳しい条件のものに合わせられます。 「タブ1:オーバーライドしない、タブ2:常にYESを返す」だと、画面は回転しません。 「タブ1:常にYES、タブ2:LandscapeRightの時だけYES」だと、画面は常に右向きになります。 このように、Tab Bar Applicationだと、画面ごとに向きを変えることが出来ないようです。 そのような場合、仕方ないので手動で回転させましょう。 – (void)viewDidLoad { [super viewDidLoad]; self.view.transform = CGAffineTransformMakeRotation(M_PI * 0.5f); //90度回転 } これで一応回転できます。 なお、InterfaceBuilderを横にしたい場合は、右上の矢印をクリックすればOKです。 見つけるのに30分かかりました。わかりにくい。

