2010-09-01

プロパティにブロックを設定したい場合にいつも忘れるので記録

@property (nonatomic, copy) void (^callEventHandler)(CTCall*);

括弧の中に ^ と宣言したい名前を書くと。はい、覚えましたね。

copy じゃなくて retain でもいいんだろうか?

2010-08-10

ブロックを使うとiPhone OS 3での動作は不可能ということを再度確認

個人的にはiOS 4以前のコードは書かないことに決めていますが、そうはいってもお仕事です。未だにiPhone OS 3向けのビルドも作ってます。でも一度ブロックの使いやすさを味わってしまうと、もうなんか使いたくって仕方のない状態。なんならiOS 4専用の部分だけでも条件分岐を入れてブロック使わせてもらっていいかな?という検証。

結論:ブロックを使ったコードがバイナリに含まれているとdyldのリンクエラーで起動すらしません。


Tue Aug 10 12:48:26 unknown UIKitApplication:xxx[0xd506][2007] : dyld: Symbol not found: __NSConcreteStackBlock
Tue Aug 10 12:48:26 unknown UIKitApplication:xxx[0xd506][2007] :   Referenced from: /var/mobile/Applications/5DBA5BE0-0517-4ABB-AF15-C4006334BF74/Xxx.app/xxx
Tue Aug 10 12:48:26 unknown UIKitApplication:xxx[0xd506][2007] :   Expected in: /usr/lib/libSystem.B.dylib

まぁ、自分のアプリケーションだったらコードもコントロールできるけど、使っているライブラリなんかがブロック使い出したら、iPhone OS 3向けのビルドはもう作れないと言うことですな。

2010-07-28

駅ベル - 1.1.0 バージョンアップのポイントをまとめました


  • 駅までの距離に従い、精度を上げるようにした
    • アラームが正しく動作する率がアップ
    • 目的地まで遠い場合にはバッテリーの持ちアップ
  • iPodで音楽再生中にも、ちゃんとアラームが鳴るように
  • バックグラウンドでも、正しく音が鳴るように
  • バックグラウンドでも、バイブレーションが動作するように
  • 設定画面を追加
    • アラームの音を変更可能に(4種類内蔵)
    • バイブレーションを選択可能に(iPhoneのみ)
    • アラーム開始距離を変えられるように(右図)
  • iPhone 4 Retina Display対応(持ってませんが)

実は今回の一番の見所は、内部のロケーションマネージャの使い方を1から見直して、完全に新しい実装で書き直しました。本当に最小限の必要としている部分でしかロケーションマネージャーを使わないように細かいチューニングを行ったので、バッテリーの持ちは前のバージョンよりもかなりよくなっています。使っているときはステータスバーのロケーションインジケータが出るので、画面ごとに出たり消えたるすることで確認できると思います。

ロケーションマネージャについては、iOS4のマルチタスキングの売りの一つだけに、バッテリーの持ちとの新たな戦いの部分、別エントリーで書きます。

駅ベルのバージョンアップでリジェクト食らいました。その顛末。

今回の駅ベルのバージョンアップは、バックグラウンドで音が鳴らないという部分の対応。UILocalNotificationに任せておけばいいかなと思ってたんですが、ちゃんと音が鳴って欲しいという要望が強く、対応することに。

長いWaiting for reviewの期間を過ごして、なんといきなりリジェクト。その理由がこれ。
We've completed the review of your application; however, because no audible content is played when the application is in the background, we cannot post this version to the App Store. We have included additional details below to help explain the issue. We hope you’ll consider revising and resubmitting your application.
iOS4向けのマルチタスキング対応アプリケーションの一つの機能、バックグラウンドでの音声再生機能を使いたいためにフラグを付けたんだけど、それが裏目になった模様。おまえのアプリケーションは音を出して内じゃないか、と。ふーむ。

そりゃぁ、カリフォルニアではまだ鳴らないっつーの(笑)。どうもアプリケーションの動作を正しく理解してもらえてない模様。普段なら慌てるところですが、どうせ自分のアプリケーション、落ち着いて対応してみました。一度Rejectedになっちゃっているので、バイナリを再度アップロードしないでも再審査してくれるか不明だったので、ちゃんと行くかどうかのテストケースになります。

いろいろ騒ぐ前に、まずはちゃんとレビューチームとコミュニケーションを開始することが一番です、と言うアドバイスももらったので、まずはメール。

Dear review team,
My application uses audio to notify user as alarm sound. My application has to play sound in background mode, and I have no idea without adding "audio" flag. 
The Apple engineer I met at the WWDC Lab said, only way to play sound is to add "audio" flag in UIBackgroundModes. If still you reject my app, please tell another way to play alarm sound in background. I think that's not fair.
- My app plays audio when the device close to the station.
- Playing audio in background needs "audio" flag in UIBackgroundModes.
Other audio application can be paused. My application is also paused until it reaches to destination, isn't it?
Please re-think about this.
Yosuke Suzuki
で、その晩はMOSA entranceがあったので、その場でリジェクトくらったーとネタにしてたりしていたんですが、裏ではことが進んでおり、今朝になってメールが届いてました。

Thank you for you email and clarification.  We are proceeding with the review and will update you with further status as soon as we are able.
Thank you for your continued patience.
短い。あまりに短いが、そしてアメリカ人、決してわびの言葉はないが、ちゃんとスムーズに対応してくれました。
無事にリリース。

教訓。リジェクトされても慌てず騒がず、ちゃんとレビューチームとお話しはしましょう。返事もくれます。他の「Contact us」系のメールと違ってスムーズです。


2010-07-08

CoreDataと再度向き合うことを決定。その前に前回の反省。

昨年からやってるランブリンのデータ部分、当初CoreDataを使っていたんだけど、どうにも使い勝手も悪く感じて、とどめはマイグレーションではまってバージョンアップでトラブル。これでもう、次のバージョンは自分で作ったCoreDataぐらいの互換レイヤーに切り替えよう、というのが今年の2月。

ある程度の時間をかけてMoreDataと言うモノを作り上げて、ランブリン 2.0のコアに使ってみたんだけど、結論から言うとあまり芳しくない状況。特にメモリ効率が極端に悪くなってしまったのが大きな誤算。SQLの使い方にはある程度自身があったんだけど、スレッド・セイフティの確保やフォルトの仕組みなんかを入れていくと速度も芳しくなく、使い勝手やマイグレーションの仕組みは直接的でよかったんだけど、全体的にいわゆる失敗と判断せざるを得なくなってしまった。

メモリ周りはやっぱり難しくて、要はキャッシュの話。何をいつ忘れるのか、これを正しく実装するのが至難の業。iOS4にはNSCacheというクラスが導入されているのも、キャッシュの難しさを表している一端と言えよう。

と言う状況で挑んだ今年のWWDC。事前に去年のビデオでCoreDataを勉強し、ドキュメントももう一度読みこんで、果たして自分はCoreDataの何を間違えていたのか、そういう視点でいろいろと検証していった。結論として


  • CoreDataをいわゆるデータベースととらえていてはダメ。単なるデータを保存する場所ではなく、データが生き続ける環境を提供してくれる環境であって、データをそこから取り出してしまっては、メリットの大半を消すことになる。
  • 同じ理由で、CoreDataを簡単なDBMに見えるようなラッパークラス経由で使ってはダメ。ちゃんとコンテクストを意識して、正しく使わないと意味がない。中途半端なSQLの知識が邪魔をしたのは否めない。
  • マイグレーションは後々絶対はまる場所なので、最初から経験を積んでおくべき。ライトウェイトだろうとなんだろうと、アプリを出した後は実際にデータがたまってしまった状況でテストも出来ないので、かならず各バージョンのデータファイルを保存しておくべき。後から手に入れるのはとても大変。
  • スレッドは最小限に。でも一つは使う。なのでNSManagedObjectIDは登場する。
こんな感じだと思う。もう一度CoreDataに手を出す前にまとめておきたかった。数ヶ月後に何を思うか。

2010-07-07

配列の配列からオブジェクトを探して、そのindexPathを返す例。powered by Block



表記になれればきれいに書けるな。スクリプト言語に慣れ親しんでおいてよかったなぁ。

2010-07-06

言語設定を変えるとバッググラウンドで走っているアプリは殺される

iOS4になって、アプリを開いている最中に環境設定も開けるようになったわけで、ドキュメントにもそれに備えろよ、と言うことは書いてありますが、じゃあ根本的な設定が変わったらどうするの?と。その最たるモノが言語設定。途中で変わると画面から何から作り直さなくてはいけないので、どうなるかと試してみた。
まあ、当たり前と言えば当たり前だが、アプリは黙って殺されます。初期化にし直しましょうと言うことでしょうか。

NSStringのフォーマット文字列生成で位置指定が出来る!

NSStringのフォーマット文字列生成で、 %n$@ というのが使える! (nは数字)

これまでは、必ず

[NSString stringWithFormat:@"Hello %@, (%@)", param1, param2];

のように順番に使われるしかなかったんですが、


[NSString stringWithFormat:@"Hello %2$@, (%1$@)", param1, param2];

のようにすれば、コード中の順番に関係なく文字を埋め込めると言うことです。
知らなかったよ、早速試してみよう。


※ 数字は1から始まるので注意。

ネタ元 : WWDC 2009 Session 106 - Building Localized Mac and iPhone Applications

2010-06-30

古いXcode用のアイコンを作ったよ - Xcode aged


http://bit.ly/aIshfv

焼けた青写真てな感じにしてみました。もう、Xcodeだらけでわかんないから!

icnsファイルなので、Xcodeのパッケージを開いてResourcesの中に突っ込んでね。

2010-06-24

駅ベル - 乗り越し防止アラーム

iPhone 4で盛り上がる中、ようやくバスケ個人名義の最初のアプリ。「駅ベル」が公開されました。

http://itunes.apple.com/jp/app/id377891789?mt=8 #iTunes

駅ベルとは何か?簡単に言えば、目的の駅に近づいたらアラームを鳴らしてくれるソフトです。全国の駅情報をekidataさんからいただきましてアプリ内に最初から収めてありますので、簡単に目的地を探すことができます。

そして、なんと言ってもiOSの各種機能に対応しています。Fast App Switchはもちろん、iOS4の目玉、マルチタスクにもちゃんと対応しています。バックグラウンドにいても監視は続けますので、ウェブをみたりゲームをしていても大丈夫です。Local Notificationを使ってアラート画面が表示されます。iOS 4で追加された新しい位置情報取得の仕組みを使っているので、これまでのアプリよりもバッテリーの減りも少なくてすんでます(それでも結構使いますが)。バックグラウンドに回ったときの挙動も、WWDCで学んだことは実践してますので省メモリ化もできているはず。

このアプリ、SDKが公開された2年前から作り始めたモノで、なかなか完成しなかったのです。だって監視している間アプリを終了させられないわけで、できることと言えば音楽を聴くことだけ。電源をスリープにしてしまうと、位置情報の精度がまったく当てにならず。アプリ内にブラウザを入れたりTwitterみれるようにしたり、いろいろ工夫してみたんですがどうもしっくりこず。

が、iOS 4になってアプリを後ろに回せるようになったことでがぜん盛り上がりました。ちゃんと位置情報もバックグラウンドにいながら取得できるわけで、これはオレのためのアップデート!wと勝手に理解して一気に仕上げました。と言うわけで無事iPhone 4の発売日にリリース。

しかし、長かった〜。リリースまで2年3ヶ月は自分の中でも最長記録。この二年間、各所でデモなんかをしてましたが、会う人会う人に、あれまだ出てないの?となじられてきましたが、それも今日まで。胸を張ってリリースされてます!と言えますよ。でましたよ!

2010-06-18

WWDC 10 - みとくべきセッションビデオ

全部なんだけどねw

とりあえず自分がみたセッションで面白かったモノ、見逃したモノを列挙。随時更新していきます。


Session 116 - Model-View-Controller for iPhone OS
リピートセッションまで行われた人気セッション。参加者曰く、刺激になりますよーとのこと。
実際のところMVCを考えるための現実的解を示してくれます。これはいいセッション。

Session 207 - Network Apps for iPhone OS, Part 1
Session 208 - Network Apps for iPhone OS, Part 2
ずっと昔からDTSで活躍するQuinn the Eskimoさんがネットの難しさを語ります。Part2は必見。RunLoopとスレッド。GCDの時代はまだやってこない、など。


Session 103 - iPad and iPhone User Interface Design
毎年同じような内容と言いながら、iPadでいったんリセットされた似等しいインターフェースデザインについてみときたい。面白かった。

Session 104 - Designing Apps with Scroll Views
長蛇の列ナンバー1だったかもという人気セッション。ScrollViewの入れ子構造で実現する写真アプリの作り方。

Session 105 - Adopting Multitasking on iPhone OS, Part 1
Session 109 - Adopting Multitasking on iPhone OS, Part 2
iOS 4の見所No1のマルチタスクについては必見。

Session 107 - Cocoa Tips and Tricks
あの人が出ます。

Session 115 - Using Core Location in iOS 4
ローケーションの取り方がだいぶん変わってます。バッテリーに気を遣いたいアプリを書きたければ必見。

Session 206 - Introducing Blocks and Grand Central Dispatch on iPhone
Session 211 - Simplifying iPhone App Development with Grand Central Dispatch
ようやく使えるようになったブロックとGCD。

Session 423 - Sensing Device Motion in iOS 4
ジャイロが追加されたセンサー系をまとめる CoreMotion フレームワークの唯一の情報。

Session 300 - Developer Tools State of the Union
今回はツール系のフィーチャーしっぷりがすごかった。その最初としてこれだけは観とくべき。

Session 304 - What's New in Instruments
何がすごいってこんなツールを提供するアップルがすごい!

Session 306 - Automating User Interface Testing with Instruments
JavaScriptを使って自動化よ! 繰り返しテストが楽になります。多分。

Session 505 - Creating Extensions for Safari, Part 1
Session 506 - Creating Extensions for Safari, Part 2
すごく簡単に作れる。概念も理解しやすい。今日から、作るべし。

Session 130 - Future Proofing your Application
将来にわたって安心して動くアプリを作りたければ、という内容。ちょっと期待はずれではあるがみとくと言い訳になる。

まだみてないやつ。

Session 138 - API Design for Cocoa and Cocoa Touch
CocoaのAPI設計の妙を学ぶ。


2010-06-17

iOS 4のマルチタスクへの対応

前のポストで、そもそもiOS 4に対応するフェーズをまとめました。で、iOS 4に対応するとした場合、どの機能に対応するとどうなるかをまとめます。


高速アプリ切り替え
SDK 4.0でビルドすると自動的に対応します。ただし、マルチタスク自体のアプリとしては、裏に回ったときの正しい作法というものがありますので、それに従った動作が求められます。


バックグラウンド・オーディオ
Info.plistでバックグラウンドでの再生を希望する旨を記述しておくと、バックグラウンドに回った場合の音の再生処理が継続して行えます。アプリ側で特別にやらなくてはいけないことは増えませんが、メモリの使い量、I/Oの使い方など工夫しなくてはいけなくなると予想されます。

Voice over IP

Info.plistでVoIPを実装したいと記述しておくと、インターネット電話を実現するために必要な待ち受け接続への対応をシステムがやってくれます。起動し続けなくても、必要なときに起こされます。標準の電話アプリと同じような立ち位置になれると言うことです。実装は大変でしょう。

バックグラウンドロケーション
Info.plistでロケーションを取得したいと記述しておくと、バックグラウンドにいるときも位置情報を取得できるアプリが作れます。バッテリーのことを考えると一番やっかいな種類のアプリです。

タスクの完了待ち
これら上記の特定用途のマルチタスク機能と関係なく、すべてのiOS 4対応アプリは、バックグラウンドに回る前に一定期間の猶予が与えられます。まだ仕事完了してないよって場合には、ブロックで処理を記述して実行させることができます。この処理が終わるまでサスペンドはされません(見た目上バックグラウンドに回ったことにはなります)。一定時間を過ぎてもタスクが終わっていない場合、システムのやつは勝手に殺すぞと言ってますので気をつけましょう。

ローカル・ノーティフィケーション
上記のバックグラウンド処理がユーザーに通知するUIとしてローカル・ノーティフィケーションが追加されてます。

これ以上の詳しい情報は、iPhone developer登録をすればドキュメントで見れますので、各自調べること。

iOS 4への対応の仕方まとめ

未対応iOS 4テスト済みiOS 4対応
ビルドするSDK※1~ SDK 3.2~ SDK 3.2SDK 4.0 ~
iOS 4で動作するか?わからんするする
OS 3.1で動作するか?するするする※2
バックグラウンドで動作しないしない可能※3
サスペンドするか?しないしないする
アプリ切り替えリスト※4に並ぶ並ぶ並ぶ並ぶ
高速アプリ切替非対応非対応対応


※1 Base SDKのこと
※2 Deployment TargetがiPhone OS 3.1以前になっていれば
※3 追加で設定、コードの記述が必要
※4 マルチタスク切り替えのために画面の一番下に出るアプリのリスト

2010-06-03

PHP 5.3

いまさらながらPHP 5.3と向き合う。もうPHPなんかに期待しないよ、仕事でみんなと使う言語だよ。面白いことはPythonでやるよ、とPHPを見捨ててから3年。PHP 5の進化もまったく注意も払っていなかった。今更どうにもならんだろうと。

さて、今年。自分的には今のところ激動の2010年なのだが、いろんなテクノロジーがPHP 5.3へバトンをつなげてくれた。

KVS → Tokyo Tyrant → MongoDB → Lithium → PHP 5.3

実は5.3のことはあまり知らず、6.0へのつなぎ、内部文字コードがUnicodeになるよー、覚悟しとけバージョンだと思い込んでいたら、実はとてつもなく強力な機能が投入された、まるで別の言語になっていた。その二つとは、無名関数と名前空間。

無名関数=名前のない関数、昔はそんなものがなんに役立つのと思っていたが、最近のコーディングを振り返ってみると何でなくてやってこれたんだ?という思いになる。イベント駆動型のプログラミングを今までもやってく体他が、かなりの苦労と意味のない名前、特に日本人にとっては頭の切り替えを必要とする英語名をつけなければいけないという作業をやっていたことになる。

「この作業をやって欲しい、中身はこれこれこうだ」
「わかりました、それでこの作業に名前はなんでしょうか?」
「名前が必要なのか?やることはわかっただろうに」
「名前が必要なんです。決まりです」
「じゃあお掃除処理でいこう」
「すみません、英語でお願いします」
「…」

名前つけなくてよければ、これお願いですむところを、余計な頭を使わされていたことがわかる。無名関数万歳。関数が変数に入れられるとか、そういう恩恵以上に大事な要素と思う。

そして名前空間。過去に「結局クラスって名前空間、責務の分離だよね」という暴論をはいたことがある。若さ故の過ち、でも名前空間はそのくらいの大事な要素。これはクラスという機能をねじ曲げてでも名前空間が欲しいという気持ちの表れと今は擁護したい気持ちでいっぱいだ。

またPHPはここでも論争の的となるチョイスをしている。名前空間の区切り文字にバックスラッシュを採用している。もーっ!とも思うんだけど、これはたいしたことではないなと。もたらされるメリットのためなら目をつぶる。無視できる範囲。変数に$、メッセージ送信に->と同じレベル。いちいち語尾に「じゃん」とか付けるなよ的な。

ということでLithiumとともにしばらく遊んでみたいと思う。幸いSnow LeopardはPHP 5.3なので問題なし。ローカルで試せるのがうれしい。

2010-05-18

EC2のFedora8インスタンスにgitをインストールするのに最低限必要なパッケージ一覧

いつもインストールにはまるので。エラー出すの遅いよ。ぶつぶつ。

yum install gcc zlib-devel openssl-devel curl-devel perl-ExtUtils-AutoInstall perl-ExtUtils-Embed perl-ExtUtils-MakeMaker perl-ExtUtils-MakeMaker-Coverage asciidoc xmlto python-devel docbook2X

2010-03-27

SharedCenterというクラスを書いてみた

Cocoaでユーティリティ的に使うクラスの定番パターンで、singletonパターンがあります。NSNotificationCenterがいい例で、アプリケーションワイドで使う機能をクラスにする場合に便利なパターン。こんな感じ。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sayHello:) name:HelloWorldNotification object:nil];

これに従って、自前で作るシングルトンクラスもなんちゃらセンターと言う名前で作りがちです。僕の場合、


  • SupportCenter
  • ActivityCenter
  • DownloadCenter

などなど。それぞれのクラスにクラスメソッドとしてsharedCenterというメソッドを定義して使ってます。こんな感じ。

[[SupportCenter sharedCenter] alertError:error];

このパターン、便利なんですがコードの中では結局グローバル変数を使って管理するという、まああまり見たくないコードでして、アナライザーに文句言われないためにもちゃんと終了時にグローバル変数を破棄してあげる必要があったり。簡単なことだけどちょっと面倒くさい。

というわけで、メタに考えました。シングルトンを管理するシングルトンクラス、SharedCenter。

SharedCenter.h
//
//  SharedCenter.h
//  Ramblin
//
//  Created by Yosuke Suzuki on 10/03/27.
//  Copyright 2010 Kanshin, Inc.. All rights reserved.
//

#import <foundation/foundation.h>


@interface SharedCenter : NSObject

+ (id)center:(Class)cls;
+ (void)registerCenter:(id)center forClass:(Class)cls;

@end

SharedCenter.m
//
//  SharedCenter.m
//  Ramblin
//
//  Created by Yosuke Suzuki on 10/03/27.
//  Copyright 2010 Kanshin, Inc.. All rights reserved.
//

#import "SharedCenter.h"


@implementation SharedCenter

static NSMutableDictionary *sharedCenters = nil;

+ (void)initialize {
  sharedCenters = [[NSMutableDictionary alloc] init];
  
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeCenters:) name:UIApplicationWillTerminateNotification object:nil];
}

+ (id)center:(Class)cls {
  id center = nil;
  
  @synchronized(sharedCenters) {
    NSString *className = NSStringFromClass(cls);
    center = [sharedCenters objectForKey:className];
    if (!center) {
      center = [[cls alloc] init];
      [sharedCenters setObject:center forKey:className];
      [center release];
    }
  }
  
  return center;
}

+ (void)registerCenter:(id)center forClass:(Class)cls {
  @synchronized(sharedCenters) {
    [sharedCenters setObject:center forKey:NSStringFromClass(cls)];
  }
}

+ (void)closeCenters:(NSNotification *)notification {
  [sharedCenters release];
  sharedCenters = nil;
  
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

このクラスを使えば、どんなクラスでも簡単にシングルトンパターンが使えます。しかもグローバル変数は一つだけ。すっきりです。

SupportCenter.h
@interface SupportCenter : NSObject {
...
}

+ (SupportCenter *)sharedCenter; // 定義を追加
...

SupportCenter.m
#import "SupportCenter.m.h"
#import "SharedCenter.h"

@implementation ActivityCenter

// 実装を追加
+ (ActivityCenter *)sharedCenter {
return [SharedCenter center:[self class]];
}

...

2010-02-03

gitのリモートのブランチを削除する方法

$ git push origin :ブランチ名

コロンの意味がわかんないけど、とりあえず忘れないように。

Diplomacy on iPadを作る計画。

2010年、今年の個人的な目標、iPad用のアプリとしてディプロマシーを作る。iPadでやると、マップの操作性も戦術練るにもいろいろ出来そうだし、秘密交渉の演出も素敵にできそう。秘密文書が届くとか。チャットとか。あーカメラがついていれば。

Diplomacy MOE
Web上で遊べるディプロマシー。これがお手本になるはず。参考にさせてもらいます。