SimpleBoxes

iPhone/iPad アプリケーション FloatyMemo+ をリリースしました

iPhone/iPad ユニバーサルアプリケーション FloatyMemo+ が公開されました→FloatyMemo+ on iTunes Store (350円)。

[画像] FloatyMemo+ スクリーンショット

FloatyMemo+ は先日公開した FloatyMemo の高機能バージョンになります。

  • 背景画像の変更
  • メモの整列
  • メモの検索
  • メール送信・テキスト書き出し

などの機能が追加されています。

「メモの整列」は画面上に散らばったメモを綺麗に整頓する機能です。

[画像] FloatyMemo+ メモ整列スクリーンショット

どのような順番で整頓させるかは設定画面で設定できます。整列させた場合、画面上の全てのメモは最小化された状態になります。

「メモの検索」は入力されたキーワードにマッチしたメモをハイライト表示する機能です。

[画像] FloatyMemo+ メモ検索スクリーンショット

マッチしたメモだけがアクティブになります。メイン画面だけでなく、ゴミ箱内でも検索が可能です。標準の「メール」アプリケーションのように先頭行の検索バーを引き出すと、検索キーワードを入力することができます。

FloatyMemo からのフィードバックでアニメーションが重いというご意見がありました。

今回公開した FloatyMemo+ はそれらのフィードバックを頂く前に申請していたもので、まだ反映できていません。現在申請中の ver 1.01 ではその辺に関して若干の改善を行っています。

FloatyMemo の公開から日が空いてしまいましたが、実は FloatyMemo+ は一度リジェクトされています。

iPad で動作させたとき、二つの Popover が同時に開かれてしまう場面があり、それがリジェクト理由でした。

スクリーンショットも添付されていて、「ちゃんと iPad ヒューマンインタフェースガイドライン」読んでねと。……すんません、ざっくりとしか読んでいませんでした。

そんな訳で FloatyMemo 共々 FloatyMemo+ もよろしくお願いします。使っていただいた感想やご意見お待ちしています。

スポンサーリンク

iPhone/iPad アプリケーション FloatyMemo をリリースしました

iPhone/iPad ユニバーサルアプリケーション FloatyMemo が公開されました→FloatyMemo on iTunes Store

[画像] FloatyMemo メイン画面スクリーンショット

FloatyMemoは iPhone/iPad 向けに開発されたシンプルなメモアプリケーションです。いわゆる「付箋メモ」アプリケーションで、作成したメモを画面上の好きな位置に「置く」ことができます。

縦画面・横画面どちらの画面モードでも動作します。マルチタッチを活かしてピンチ・回転ジェスチャーでメモのサイズを自由に微調整することができます。

先日リリースされた ATOK pad との連携もサポートしています。設定画面において「連携強化」をオンにすると、メモ編集に常時 ATOK pad を利用するようになります。

検索やメモの整頓などの追加機能のある有償版 FloatyMemo+ も近日公開予定です。

Re: 初めてiPhoneアプリを作る人が使いたがる機能」でも触れましたが、初めてのアプリらしく (?)、ピッカーを使っています。

[画像] FloatyMemo 編集画面スクリーンショット

使い勝手……悪くなったかな?おそらく iPad だと占有面積が大きすぎますね。

FloatyMemo では、利用している nib ファイルは全て iPhone/iPad で共通です。コード内で「iPad なら PopOver を利用する」というような分岐はいくつかの場面で行っていますが、思った以上にほとんどコードは共用できました。

現在 iPad を所有していないので、iPhone のみ対応のつもりで開発はじめたんですが、試しに iPad 向けにビルドしてみたら、何となく動作してしまったので、そのままユニバーサルアプリケーションとしてリリースしています。

編集画面にはモーダルビューを利用しています。メモの拡大アニメーションをさせるので、最初はモーダルビューの表示にアニメーションは利用しないつもりだったんですが、横画面でのビューがずれるという Cocoa Touch のバグ (?) のため、フェードインアニメーションでちょっと妥協。思ったよりも自然なので、結果オーライかな。

というわけで、初めての iPhone/iPad アプリケーション FloatyMemo をよろしくお願いします。使っていただいた感想やご意見お待ちしています。

スポンサーリンク

Objective-C で使っているマクロと Objective-C++ を Xcode で利用するときの副作用

ARRAY マクロ

小さな行列オブジェクトをよく利用するとき、

#define ARRAY(first, ...) [NSArray arrayWithObjects: first, ##__VA_ARGS__ , nil]

のようなマクロを定義しておくと便利かも。

NSArray* array = ARRAY(@"Value1",@"Value2");

のように使います。最後の要素後「nil」はいりません。

問題点は途中に改行を含めることができないこと。一行で全ての要素を定義する必要があります。

マクロといえば、

#define ApplicationName \
[[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"]

#define DocumentDirectory \
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]

#define SupportDirectory \
[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject]

#define currentOrientation \
[UIApplication sharedApplication].statusBarOrientation

あたりは定義しておくと便利かも。Objective-C はクラス名やメソッド名が長いのが多い……。

Objective-C++ を Xcode で利用したとき

Objective-C で C++ と併用する場合、Objective-C++ を使います。一般的な拡張子は .mm 。

Xcode 3.* で Objective-C++ を利用する場合 (Xcode 4.* では未確認)、ちょっとした副作用があります。

Xcode にはリファクタリング機能があります。クラス名を変更したい時やメンバー変数を変更したい時に該当箇所をほぼ自動で検索・置換してくれる機能です。クラス名を変更したときは必要に応じてファイル名も変更してくれたり……。

なかなか便利な機能ですが、これが Objective-C++ だと動作してくれません。

そんな時は一時的に Objective-C++ のファイルを Objective-C として認識させるのが有効です。

Xcode のプロジェクトに追加されたファイルは、ファイルの拡張子とは独立した形で、ファイルタイプが保持されています。

ファイルを選択して、コンテクストメニューを開いて、General タブにその設定 (File Type) があります。

私は Xcode は英語で利用するようにしているため、日本語版での名称が分かりません。General タブは「一般」タブで、File Type は「ファイルタイプ」でしょうか。

これが

sourcecode.cpp.objcpp

のようになっていると、そのファイルは Objective-C++ の実装ファイルとして設定されていることになります。

これを

sourcecode.c.objc

のように変更すると、Objective-C として認識されるようになります。

ビルド前に戻すことを忘れないようにしてください。そうしないと、Objective-C++ のファイルが Objective-C としてコンパイルされてしまうので、エラーになってしまう場合があります。

スポンサーリンク

Re: 初めてiPhoneアプリを作る人が使いたがる機能

HMDT の木下さん曰く

初めてiPhoneアプリを作る人が使いたがる3つの機能:

  • シェイク
  • フリック入力
  • ピッカーコントローラ(時計アプリとかで使われている、ドラムみたないやつ)

どれも癖があって、これを組み込んで使いやすいユーザインタフェースを作るのは難しいんだけど、みんなやりたがる。使いにくくなるからやめとけって。

[→September 2010 | HMDT Journal]

あぁ、あるあるある……。

とても分かるような気がします。他にも……

  • ピンチ
  • ローテーション (マルチタッチの回転ジェスチャー)

がありませんか?ないですか?ありますよね?多分。

シェイクは、普段ほとんど使わないので、意識しませんでした。フリックは……断念。

[余談] HMDT Journal、RSS 配信して欲しい……シイラでサポートしているので、いずれ RSS 配信してくれると思っていたんですが……。

スポンサーリンク

ブロックを使ったアニメーション処理 (iPhone/iPad, Objective-C 2.0)

iOS4 から UIView クラスにある

+ (void)animateWithDuration:animations:

というクラスメソッドを使ってアニメーション処理を行うことができます。

従来の

+ (void)beginAnimations:context:
+ (void)commitAnimations

などの一連のアニメーション関連のクラスメソッドも引き続きサポートされていますが、discouraged (非推奨) になっています。

animateWithDuration:animations: によるアニメーション処理の特徴的なところは、ブロックと呼ばれるクロージャ機構を利用しているところです。

従来のように終了処理セレクタを用意することなく、アニメーション処理を記述できるので、一般的にコードはより簡潔になります。

例えば、以下のようなアニメーション処理をするコードがあるとします。

- (void)doAnimation
{
  self.alpha = 0.1f;
  self.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
  [UIView beginAnimations:nil context:nil];
  [UIView setAnimationDelegate:self];
  [UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
  [UIView setAnimationDuration:0.3f];
  self.alpha = 1.0f;
  self.transform = CGAffineTransformMakeScale(1.2f, 1.2f);
  [UIView commitAnimations];
}

- (void)animationFinished:(NSString *)animationID  finished:(BOOL)finished  context:(void *)context
{
  self.transform = CGAffineTransformIdentity;
}

終了処理用のセレクタ animationFinished:finished:context: が必要になっています。また、beginAnimations:context: から始まって 5 つのクラスメソッドを呼んでいるのも分かると思います。

一方、新しいブロックを利用したアニメーション処理では、

- (void)doAnimation
{
  self.alpha = 0.1f;
  self.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
  [UIView animateWithDuration:0.3f
                   animations:^{
                     self.alpha = 1.0f;
                     self.transform = CGAffineTransformMakeScale(1.2f, 1.2f);
                   }
                   completion:^(BOOL finished){
                     self.transform = CGAffineTransformIdentity;
                   }];
}

のようになります。

行数的にはそれほど大きな変化はありませんが、利用しているメソッドはひとつだけ。アニメーションとして処理される部分も animations: という引数にまとまっているので、分かりやすくなっています。また、アニメーション終了処理用セレクタも必要ありません。

ブロックを利用したアニメーション処理は、簡潔ですし、なにより分かりやすくなっています。しかしながら、iPhoneOS 3.2 では利用できません。そのため、iPad 向けには今のところ旧来の方式を記述するしかないようです。

でも、一度ブロックを利用した記述に慣れてしまうと、もはや旧来の方式で記述するのは苦痛。同じ動作をプラットフォーム毎に別の記述するのも面倒です。

そこで同じ記述でどちらも動作するコードを考えてみます。方針としては、ブロックを利用したアニメーション処理を iPhoneOS 3.2 でも利用できるようにするのが目標です。

アニメーション処理を行うクラス SBAnimator を作ります。

#import <UIKit/UIKit.h>

@interface SBAnimator : NSObject

+ (void)animateWithDuration:(NSTimeInterval)duration
                 animations:(void (^)(void))animations;

+ (void)animateWithDuration:(NSTimeInterval)duration
                 animations:(void (^)(void))animations
                 completion:(void (^)(BOOL finished))completion;

+ (void)animateWithDuration:(NSTimeInterval)duration
                      delay:(NSTimeInterval)delay
                    options:(NSUInteger)options
                 animations:(void (^)(void))animations
                 completion:(void (^)(BOOL finished))completion;

@end

最初の二つのメソッド animateWithDuration:animations:animateWithDuration:animations:completion: は引数を省略したショートカットバージョンです。

+ (void)animateWithDuration:(NSTimeInterval)duration
                 animations:(void (^)(void))animations
{
  [SBAnimator animateWithDuration:duration
                            delay:0.f
                          options:UIViewAnimationOptionTransitionNone | UIViewAnimationOptionCurveEaseInOut
                       animations:animations
                       completion:nil];
}

+ (void)animateWithDuration:(NSTimeInterval)duration
                 animations:(void (^)(void))animations
                 completion:(void (^)(BOOL finished))completion
{
  [SBAnimator animateWithDuration:duration
                            delay:0.f
                          options:UIViewAnimationOptionTransitionNone | UIViewAnimationOptionCurveEaseInOut
                       animations:animations
                       completion:completion];
}

実質的には最後のものだけを実装します。

+ (void)animateWithDuration:(NSTimeInterval)duration
                      delay:(NSTimeInterval)delay
                    options:(NSUInteger)options
                 animations:(void (^)(void))animations
                 completion:(void (^)(BOOL finished))completion
{
  [UIView beginAnimations:nil
                  context:UIGraphicsGetCurrentContext()];
  if (completion)
  {
    [[[SBAnimationHandler alloc] initWithCompletionAction:completion] autorelease];
  }
  [UIView setAnimationCurve:(options >> 16) & 0x7];
  [UIView setAnimationRepeatAutoreverses:options & UIViewAnimationOptionAutoreverse];
  [UIView setAnimationDelay:delay];
  [UIView setAnimationDuration:duration];
  animations();
  [UIView commitAnimations];
}

ご覧の通り、内部では旧来の方法を利用しています。今のところ、旧来の方式は iOS4 でも利用できるので、これでどちらの環境でも動作します。

基本的には引数として渡された completion ブロックを遅延動作することさえできればいいわけで、それを実現するために SBAnimationHandler というプライベートなクラスを使います。

@interface SBAnimationHandler : NSObject
{
@private
  void (^_completionAction)(BOOL finished);
}

- (id)initWithCompletionAction:(void (^)(BOOL finished))completion;

@end

@implementation SBAnimationHandler

- (id)initWithCompletionAction:(void (^)(BOOL finished))completion
{
  if (self = [super init])
  {
    _completionAction = Block_copy(completion);
    [UIView setAnimationDelegate:[self retain]];
    [UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
  }
  return self;
}

- (void)animationFinished:(NSString *)animationID 
                 finished:(BOOL)finished 
                  context:(void *)context
{
  _completionAction(finished);
  [self release];
}

- (void)dealloc
{
  Block_release(_completionAction);
  [super dealloc];
}

@end

SBAnimationHandler 側でアニメーション終了処理用のセレクタを定義しているので、呼び出し側には追加のセレクタは必要ありません。

終了処理セレクタでは、単純に保持していたブロックを実行しているだけ。若干特殊な部分があるとすれば、アニメーション終了処理を実行したら、SBAnimationHandler のインスタンスは必要ないので、[self release]; をコールして、自己破棄しているところぐらいでしょうか。

ブロックはスコープを抜けると破棄されていまうので、_completionAction = Block_copy(completion); で保持するようにしています。

リファレンスカウンタの絡みで [UIView setAnimationDelegate:[self retain]]; と若干ハック的なことをしていますが、あまり突っ込まないでください。

これによって iPhoneOS 3.2 だろうと iOS4 だろうと、どちらも

- (void)doAnimation
{
  self.alpha = 0.1f;
  self.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
  [SBAnimator animateWithDuration:0.3f
                       animations:^{
                         self.alpha = 1.0f;
                         self.transform = CGAffineTransformMakeScale(1.2f, 1.2f);
                       }
                       completion:^(BOOL finished){
                         self.transform = CGAffineTransformIdentity;
                       }];
}

のように記述できます。

とりあえず、iPad シミュレータと iPhone シミュレータでのみ動作確認をしています。私の環境では確認していませんが、PLBlocks を利用すれば iPhoneOS 2.2 からでも利用できるようになるんじゃないでしょうか。

今回作成したコードは、アーカイブとして置いてあります。

コード SBAnimtor をダウンロード

スポンサーリンク

Safari on iPhone 対応に関するメモ

Serene Bach 3.00b027 から iPhone/iPod touch 用の Safari 向け管理画面インターフェースをサポートしました。

Android のブラウザも対応したつもりでしたが、先程エミュレータで確認したら、認識されていませんでした。近日中に修正する予定。

iPhone/Android で採用されているブラウザエンジンは Mobile WebKit (Mobile Safari) と呼ばれるもので、WebKit のサブセットになっているようです。

デスクトップ版 Safari と Mobile Safari で挙動が違うことは知られている通り。JavaScript ではマウスイベントハンドラ、実行時間の制限などがあり、読み込める画像のファイルサイズに制限があったりします。

ここでは Windows 版・Mac OS X 版の Safari をデスクトップ版 Safari と呼んでいます。

今回、Serene Bach 3.00b027 開発中に気づいた細かーーい挙動の差異をメモ。

head 要素内で document.write は使えないっぽい

document.write 自体は使える様子ですが、実行場所を選ぶようです。

詳細は検証していないのですが、とりあえず head 要素内に置かれた scriptdocument.write は実行できないようでした。

どうしてそんな場所で document.write を実行しているのかというと、外部 js から別の js ファイルをロードするため。head 要素内に DOM で appendChild する方法もあって、個人的にはこっちの方がしっくりするんですが、やや古い Safari で動作しなかったという経緯があり、document.write を使っていました。

td 要素 (多分 th 要素も) の display スタイルを変更できないっぽい

これも詳細は検証していませんが、例えば、以下のようなスタイル……

table#specific > tbody > tr > td {
  display: block;
}

は動作しませんでした。

ある特定の項をブロック要素として動作させたい意図があったのですが、動作しませんでした。デスクトップ版 Safari では動作するので、Mobile Safari の特徴の様子です。perl スクリプト本体の方は変更なしでいけるかとも思ったのですが、この仕様 (?) のため、ダメでした。

contenteditable は利用できない

Preparing Your Web Content for iPad: Technical Note TN2262: Preparing Your Web Content for iPad でも触れられていますが、contenteditable は利用できないようです。

おそらく designMode もダメでしょう。とりあえず、Serene Bach 3 で利用されているカスタム CodePress は利用できませんでした。

スポンサーリンク

我ながら頑張った

  • 2010.06.23 Wednesday
  • life

KLab×はてな エンジニア応援ブログコンテストという企画があったので、ちょっと便乗して自分語り。

武勇伝というと大げさですが、私にとってチャレンジだったことをいくつか。

  • 海外で働きはじめた
  • 「死んだ」プロジェクトを復活させた

これまでに記載した内容と重複する部分もあります。ご了承ください。

日本を出るという選択

おそらく私にとって今のところ最も大きな転機は、やはり「日本を出て海外で働きはじめた」ことでしょう。

最近「パナソニック採用の8割外国人」や「楽天・英語が出来ない役員は…… (三木谷社長インタビュー)」でニュースになったり、「死ぬほど英語を勉強してきたからわかる、英語学習の限界」という記事を読んだりしたので、それと若干絡めて。

実のところ、これまでにも散々言ってきたように、英語が大の苦手で「海外で暮らす」ことが自分にとって選択肢になり得るとは、その当時思っていませんでした。

楽観主義であまりに計画性のない私をしっかりと支えてくれたのは嫁さん。移住に関しては、案外あっさりと決断してしまったような気がするのですが、綿密な情報収集と現状分析に関しては嫁さん抜きでは無理でした。

ニュージーランドの永住権を取得するためには IELTS という英語のテストで、ある基準をクリアする必要がありましたが、嫁さんの用意周到な準備のおかげで、私は IELTS の勉強だけに集中していたとも言えます。

「日本を出て海外で働く」というと人によってはものすごい前向きな挑戦のように感じる人もいるかもしれません。

私の場合、その当時住んでいた場所から「物理的に距離のある場所」で暮らさないと精神的にきついと思った……簡単に言えば、「逃げ出したかった」という面があったことだけは書いておかないといけないと思います。

ある意味切羽詰っていたので、思い切った行動を取ることができたのかもしれません。

就職するまで

ニュージーランドの永住権を無事取得し、実際に移住する前に一週間ほど下見旅行に行きました。

下見旅行では、就職活動の事始めとして幾つかのエージェントにコンタクトしてみましたが、私のつたない英語では、会ってもくれません。数名のエージェントと電話越しに話しましたが、相手が何を言っているのかよく分からない。

一人からは呆れたように「あなたの英語ではニュージーランドで働くのは無理」とはっきり言われたのだけは覚えてます。

結局就職活動以前の問題で、当面は英語を鍛えるのを第一に考えることにしました。移住してしばらくは語学学校に通ったり、地元のコミュニティスクールに通ったり……。

最初の三ヶ月は本格的に就職活動はしていませんでしたが、たまたま通学していた英会話学校では、移民向けの就職活動に力を入れていて、そこで知った移民向け就職セミナーなどは参加していました。

就職活動に本腰を入れるようになってからは

  • 新聞などの求人広告に目を通す
  • ウェブ上の求人サイトに登録する
  • 就職斡旋エージェントに会う・電話する
  • 会社に押しかけ、履歴書を置いてくる

などなど。

ニュージーランドには基本的にコネが全くない状態でした。とりあえず、上がってくる求人を嫁さんがざっくりリストアップして、その中から私が自分のスキルに関連した内容に絞り込んで応募するような作業を日々繰り返しました。

当時応募した会社は延べ数で 150 社以上になります。当時の風向きもあり、書類選考で落とされてしまって、まず土俵にも上がれないような感じでした。

面接のチャンスは突然やってきました。面接をしたい旨の電話がかかってきて、あれよと思う間もなく、決まってしまったような……。

最初の面接は、人事マネージャと開発マネージャとの面談。

技術的なバックグラウンドの確認はもちろんですが、どうしてニュージーランドに移住したのかなど、一般的な質問も……。どのぐらい話したのかほとんど覚えていませんが、一時間は話していなかったような気がします。ここで感触が良かったようで、確か次の面接の約束もしたような気がします。

二回目の面接は、技術面接。複数のシニアエンジニアを前に、プログラミングに関する技術問題を解きます。

基本的なアルゴリズムとそれに関するメモリ効率・計算量オーダーの理解など。C 言語のプログラマの募集だったので、C 言語に関する質問もありました。ホワイトボード・紙を使って説明します。

基本的な面接の流れは、今でもそれほど大きくは変わっていないようです (とりあえず、現在働いている会社では。他所の会社はよく分かりません)。

死ぬほど英語を勉強してきた方と違って、私は英語に関して半ば放棄していました。その分、技術的な方面に注力してきました。注力というか、ぶっちゃけて言うと、嫌いな英語を避けて好きなことをやってきたという感じ。

基本的に「モノ作り」が好きで、プログラミングはソフトウェアという「モノ」を作るために必要なツールの一つでした。幸運なことに世界で主流になってるほとんどのプログラミング言語は世界で共通です。

なでしこMind など現在現役で利用されている日本語で記述可能なプログラミング言語も存在します。日本語で記述可能なプログラミング言語というと、どうしても「ぴゅう太」を思い出してしまう、そんなベーマガ読者だった私、というのは余談です。

「プログラミング言語」は、ある種の強力な世界共通の言語です。英語を話せる人は世界にごまんといますが、プログラミング言語を理解し、記述する能力のある人は、まだまだ少ないと言えるでしょう。

幸い日本はプログラミング言語を学ぶ環境が充実していると思います。英語以外の言語で日本語ほど技術文書が手に入りやすい言語はあまりないような気がします。

もっともそれ故に英語の技術文書を読んだ時にすっと頭に入ってこなかったりするんですが……。

エンジニアとして

ソフトウェアエンジニアとして海外の現地会社に就職することができました。

英語の能力はもちろん必要で、それを向上することもきっちり求められましたが、それ以上に技術的なスキルが重要であるというのがはっきりしています。

携わったのはコンシューマ向け製品開発で、よりユーザーに近い部分を担当したことは、私にとって新鮮で刺激的でした。

思いついたアイデアはつたない英語で伝えきらないので、開発中のソフトウェアに組み込んで、プロジェクトマネージャやシステムエンジニアに直接売り込み。……「こんなのどう?」

あるプロジェクトでは、新しいユーザーインタフェースを作りこみました。

新しいインタフェースは、斬新でしたが、どうやって使うのか初見では分かりづらい。……そもそも説明が必要なインタフェースは、あまり出来が良いとは言えないのですが、スケジュール的に押しています。

ミーティング後、大体一時間ぐらいでしょうか、ちょっとしたヘルプをアニメーションで表示する機能を簡易実装して、システムエンジニアにデモンストレーション。その時のマネージャやエンジニアの笑顔は今でも覚えてます。

世界的なリセッションの影響は、辺境の地ニュージーランドにも襲いかかります。私の会社も影響を受けて、大規模なリストラがありました。

それまでにも何度かリストラはありましたが、その時は主要なメンバーもごっそりいなくなってしまうような大きなもの。社員は半数近くになってしまったでしょうか。今にして思うと精神的にきつかったみたいで、身体にもその影響がはっきり出たりしました。

リストラのあおりを受けて、進行中のプロジェクトも軒並み中止に。私がテクニカルリーダーとして進んでいたプロジェクトもキャンセルされました。

代わりにそれまで開発していたソフトウェアからフレームワークとなるライブラリ群を抽出して開発することになりました。

キャンセルされたプロジェクトは、個人でテクニカルリーダーを担当した初めてのプロジェクトなので、思い入れがありました。マネージャからは「your child」と言われたり……。

新しく担当したライブラリ群にはテスト用アプリケーションが必要で、キャンセルされたプロジェクトで使われた部分もそのテストアプリケーションの一部に組み込みで動作していました。一時、その部分は要らないから削除しようという話もありましたが、無理して削除することもないかとそのままに。

しばらくそのライブラリ群を担当していましたが、皮となるアプリケーションの仕様がうまくまとまらず、結局プロジェクト自体を見直す羽目に。そこで白羽の矢が立ったのが、キャンセルされた私のプロジェクトでした。

  • すでにアルファ版として、ベース部分は動作している
  • 主要部分をコーディングした私がいる
  • プロジェクトスケージュールがタイト

という理由だったようです。

自分で公開しないと決めたのならともかく、自分の作ったソフトウェアが日の目を見ないことほど悲しいことはありません。やはりとても嬉しかったです。実際、嫁さんもこの時は声が弾んでいたと言っていました。

「復活」が決まってからは、仕様策定に参加したり、コーディングはもちろん、全体の進捗管理、リソース管理も必要です。リソース不足でアイコンなども私が作ったり……(これまでも小さな UI パーツは作ったりしていましたが、 私がデザインしたアイコンなどが半ば公式的に採用されてしまったのは初めて)。

プロジェクト終わりかけで決まって出てくるやっかいなクラッシュバグなどもありましたが、どうにか予定通りにリリースできました。

スポンサーリンク

Lightbox plus を使ったスライドショー

  • 2010.06.16 Wednesday
  • dev

toybox で公開している Lightbox Plus ですが、スライドショーは実現できないか?という質問があったので、適当に見つくろってみました。折角なので、公開します。

内容としては、タイマーで次から次へと画像を表示するだけの処理で特に難しい内容ではありません。

公開しているサンプルスクリプト lightbox_plus.js では、末尾で


Spica.Event.run(function() { 
  var lightbox = new Lightbox({
    // ... 省略 ...
  });
});

のようにして Lightbox オブジェクトのインスタンス lightbox を生成しています。この変数 lightbox はローカル変数なので、ブロック外部では参照できません。

スライドショーを実現するために生成したインスタンスにアクセスできるよう、lightbox をグローバル変数にします。

面倒なので、グローバル変数にしましたが、スライドショーを実現するオブジェクトを作って、その中で Lightbox のインスタンスを保持するという方法がおそらくスマートでしょう。

あとは生成したインスタンスに対して、タイマーを使って画像を順に表示していけば良いだけです。

とりあえず、途中で止めるなどの処理は考えず、ページ内の全ての Lightbox 対象の画像を表示したらスライドショーを終わらせるという方針で作成してみます。

サンプルスクリプト lightbox_plus.js の末尾を削除して、代わりに Lightbox を設置する html の末尾に以下のような記述を追加します。


<script type="text/javascript">
var lightbox = new Lightbox({
  // ... 省略 ...
});
var slideCount = 0;
function runSlideShow()
{
  var num = lightbox._open + 1;
  if (num >= lightbox._imgs.length) num = 0;
  if ( slideCount < lightbox._imgs.length )
  {
    if ( slideCount == 0 )
    {
      lightbox._show(num);
    }
    else
    {
      lightbox._close_box();
      lightbox._show(num);
    }
    slideCount++;
    window.setTimeout( function(){ runSlideShow(); }, 5000 );
  }
  else
  {
    lightbox._close();
  }
}
</script>
<div><a href="#" onclick="slideCount = 0; runSlideShow(); return false;">play</a></div>

Lightbox の _show メソッドは画像のインデックスを引数に取ります。有効な数値は 0 から _imgs.length の間です。Lightbox の対象となる画像は _imgs に配列として保持されているので、その length を取れば有効引数の範囲がわかります。

Lightbox オブジェクトの _open 変数は現在開いている、あるいは最後に開いた画像のインデックスです。これを +1 することで次の画像のインデックスを特定できます。初期値は -1 なので、仮にまだ開いていなくても +1 することで 0 になり、問題ありません。

グローバル変数 slideCount はスライドショーで開いた画像の数になります。これが Lightbox 対象の画像点数に達するまでタイマーで順に次の画像を開くようにしています。

今回作成したサンプルはアーカイブとして置いてあります。

「Lightbox plus スライドショー」をダウンロード


    window.setTimeout( function(){ runSlideShow(); }, 5000 );

およそ 5 秒で次の画像を表示するようにしていますが、表示の終了から 5 秒ではなく、_show メソッドをコールしてから 5 秒なので、短すぎるかもしれません。きちんと作るなら、ここは表示し終わってからタイマーを開始すべきです。

スポンサーリンク

ラグビー日本代表戦 (vs ノースハーバー)

  • 2010.06.05 Saturday
  • misc

最寄のノースハーバースタジアムにて、ラグビー日本代表とニュージーランド・ノースハーバー州代表の対抗試合が行われると聞いて、見てきました。

お金を払ってラグビーの試合を見に行くのは初めて。せっかくラグビーの本場 (?) にいるので、スーパー 14 と呼ばれるプロラグビーの試合やオールブラックスの試合などは、機会があれば是非見てみたいと思っていたのですが、これまで機会を逃してしまっていました。

[写真1]

ノースハーバースタジアムは、オークランドだとイーデン・パークの方が大きいですが、ノースショアでは最大級のスタジアム。来年行われるラグビーワールドカップの会場としても使われます。

[写真2]

一階客席とグラウンドは至近距離。全体を見渡すのは若干不利ですが、迫力はあります。この日は日本代表戦の前に地元カレッジの対抗試合が前座としてありました。

[写真3]

試合の前座に和太鼓のパフォーマンス。和太鼓のパフォーマンスはこちらではそこそこ見かけます。メンバーは日本人だけじゃなかったり……というかたいてい日本人は少数だったりしますが。

[写真4]

会場で配られていた旗。日本バージョンとニュージーランドバージョンがありました。どちらもノースハーバーチームのロゴが裏にプリントされています。透けて見えるのが分かるでしょうか。

[写真5]

ラグビーの国代表は伝統的に愛称があるようです。ニュージーランド代表は言わずと知れた「オールブラックス」。オーストラリア代表は「ワラビーズ」、南アフリカ代表は「スプリングボックス」などなど。日本代表の愛称は「チェリーブロッサムス」……。

[写真6]

日本代表の対戦相手、ノースハーバー。ニュージーランドでは、オールブラックス (国代表) を頂点として、地区代表・スーパー 14 → 州代表・NPC のようなピラミッド型の階層構成になっています。州代表からの選抜メンバーで構成された地区代表、その地区代表の選抜メンバーで構成されたオールブラックスという感じ。

[写真7]

ラグビー素人の私から見ても、前半は終始ノースハーバーに圧倒されてしまっているような展開。

ラインをスルスルっとあっさりと抜けられてしまう場面が何度も見受けられました。押され気味なので、せめてキックで距離を取ろうとしたりするのですが、それもミスキックになってしまったり……。

前半、ノースハーバーは 1 トライを含めた 16 点をあげますが、一方の日本代表は 0 点。

[写真8]

前半、ほぼ唯一のチャンス。結局守りきられてしまうのですが……。

こちらは初冬。夜というのもあって、かなり冷えてこんでいます。選手の吐く息や身体から出る熱気が湯気となって見えますが、特にスクラムを組むとそれが塊のようになるので、はっきりと分かります。

[写真9]

後半の後半になってきて、遅ればせながら日本も反撃。最後の方はどうにか主導権を握るような形で 3 トライを奪います。若干エンジンがかかるのが遅くて、前半と後半始めに取られてしまった得点には届きませんでしたが、最後はなかなか盛り上がって終わりました。後味は悪くなったような気がします。

日本代表が弱いというよりもニュージーランドが強いという感じ。一時に比べ、圧倒的に強くはなくなったとも言われるニュージーランドですが、やはり日本と比べるとまだまだその力の差はかなりあるんだなぁと思いました。

スポンサーリンク

大前研一氏の特別講演

  • 2010.05.17 Monday
  • misc

日本への帰省の際、Information On Demand Conference Japan 2010 に参加してきました。こういう機会は日本で働いていたときでもあまりなかったので、なかなか新鮮でした。

二日間に渡っていくつものセッションがありましたが、初日には大前研一氏による特別講演「緊急提言!新しい 10 年へ向かって、今、日本は何をなすべきか」がありました。

スライドなど一切ない講演でしたが、さすがに大前氏の話す内容は明快で、メモもとても取りやすかったので、記録として残しやすい印象がありました。

ここでは大前氏の特別講演の内容を私がまとめたものを公開します。以下の内容は、その場で取ったメモを元に私がまとめたものです。正確性に欠けると思いますが、ご了承ください。

四つの図は私が手書きしたメモをスキャナで取り込んだものです。

変わってきたお金の流れ

[図] 手書きメモその 3

「以前から『緊急提言』と何度も緊急な提言を行なってきましたが、一向に政府はやってくれません」というつかみから入る大前氏。

ここ数年で「お金の流れが変わってきた」と大前氏は言います。

300 年から 200 年前は、先進国が南の途上国を軍事で植民地化していくという、軍事力による流動でした。

50 年ほど前になると、先進国が途上国に ODA という形を使って政府レベルで資金を流動させていました。

これがここ数年で変化しています。先進国にはお金が余るようになってきました。その額は 8000 兆円に上り、これらを先進国で回して利益を得ようとしてもほとんどリターンがない状態になっています。その半数の 4000 兆円はホームレスマネーになっています。

これらの余ったお金は、先進国の株式市場を通して、中国・インド・インドネシア・トルコといった国々に流動するようになってきました。先進国もそうでしたが、まず為替が上がって、その後、株式が上がります。こうした国でもこの傾向が見えています。

先進国のお金を持った個人から途上国にある民間企業というお金が流れが人類史上初めてできています。

鍵を握る国

[図] 手書きメモその 4

大前氏が「企業参謀」(1985) を書いた頃

  • Company
  • Competition
  • Customer

という「3C」が企業のキーポイントでした。

それが「ボーダレス・ワールド」(1990) では

  • Investment
  • Information
  • Industry

という「3I」に加えて

  • Capital
  • Communication
  • Currency

の「3C」がキーポイントになっています。アメリカ GE / IBM という巨人が information だけで 5 万人雇用するという話があったりしましたが、実際インドのとあるシステム会社では SE だけで 5 万人から 7 万人いたりします。そういう時代になっています。

先の話でも出た、ブラジル・ロシア・インド・中国……これらは BRICS とよばれて非常に勢いがあります。

インドネシアもかなり勢いがあって、インドネシアでは BRICS にもう一つ「I」を加えて「BRIICS」と言ってくれと息巻いていたりします。

こうした勢いのある国は共通点があって

  • 人口が 5000 万人以上であること
  • 平均年齢が 25 〜 30 歳と「若い」国であること
  • ひとりあたり GDP が US$3,000 以上であること

インドネシアは人口 2 億 4000 万人で、平均年齢が 27 歳です。インドネシア以外にもトルコ・タイ・ベトナムといった国が該当します。

基本的には年収 US$2,500 〜 3,500 あたりの人たちが最も多く消費します。あまり世界的な景気に左右されないのが特徴で、いわゆる「消費する人々」です。

EU やアメリカと比べて日本にとって大きな優位点は、これら「消費する人々」がアジアという近隣だけでも 7 億 4000 万人、つまり日本が 7 つ分あるような規模でいるわけです。

これからの十年、こうした国々が日本が生き残っていくためのキーになっていくでしょう。

十年後の経済ランキング

[図] 手書きメモその 1

今後十年ということで、十年後の 2020 年の世界の経済ランキングを予想しています。

実は今でも世界一位の経済大国は、アメリカではなく「EU」であると明言します。「EU」は 28 カ国からなる地域統合体ですが、経済的にも法律的にも「国」と言えるだけの条件を備えているとのこと。

世界一位の地位は十年後も EU であり、それに続くのがアメリカだろうと予想しています。この順位は 2010 年も 2020 年も変わらないということです。

2010 年の時点では、それに日本が続いていますが、十年後には中国が三位に、インドが四位と続きます。中国は二十年ほど前は、九州と同程度の GDP しかありませんでしたが、今では日本と横並び、今年中にも日本を抜くと予想されています。インドは遅くとも 2025 年には為替で抜いているでしょう。

五位・六位には、インドネシア・ブラジルが入り、日本は七位になるであろうと予想しています。

日本が生き残っていくために……

[図] 手書きメモその 2

こうした今後十年の動きの中で、日本はどのように立ち振舞っていくべきか。最大のネックとなるのは「人材」であろうと大前氏は指摘します。

輸入して調達することのできる「モノ」ではなく、現地の内需に応えることができる人材の有無が勝負になります。

日本経済 7 つ分もある市場の内需に応えることができれば、今までと同じ「いい商品をより安く!」という形のビジネスでいけるわけです。

日本が得意とするのはインフラ作りで、品質などでは他国を圧倒しています。ところが、個々の連携がバラバラで柔軟性にも欠けています。日本はトータルなサービスとしてこれらを提供するのが苦手です。新幹線もそれで負けています。

新幹線のダイヤは他国では真似できないほど、高度な運用ノウハウ BOT (Build-Operate-Transfer) もあります。ただし、トータルでパッケージする指導者・会社がないとダメです。トータルで勝つことが必要になってきます。

国民 DB とクラウドコンピューティングで全国規模のインフラを構築し、住民サービスをブラウザから行えるようなシステムを作り上げれば、システム会社はまだまだいけます。

日本 7 つ分の市場を求め、アジアに出る勇気が必要です。人材づくりには二十年かかります。今すぐ取り掛かる必要があります。

スポンサーリンク

6/25