SimpleBoxes

Visual Studio 2010 Express for Windows Phone を Windows 8 にインストール

[図] Visual Studio 2010 Express の起動画面

Visual Studio 2010 Express for Windows Phone を Windows 8 にインストールする手順について、備忘録

元記事 に全ての手順ならびに要因が詳しく説明してあります。

  1. Windows Phone SDK 7.1 をダウンロード・インストール
  2. Games for Windows Marketplace Client をダウンロードして・インストール
  3. 1. でダウンロードしたインストーラを再度起動して、修復 (repair) を選択
  4. Windows Phone SDK 7.1.1 Update をダウンロードして、SDK 7.1.1 にアップグレード

3. のステップが終了した段階で、Visual Studio 2010 Express は起動できるようになりますが、エミュレータが正しく起動しません。SDK 7.1.1 にアップグレードすることでエミュレータも動作するようになります。

はてなブックマーク - Visual Studio 2010 Express for Windows Phone を Windows 8 にインストール

スポンサーリンク

iOS デバイス一覧表

iOS デバイスの一覧表を自分用に作成 (2014/11 現在)。

デバイス発売年CPU解像度iOS
バージョン2345678
iPhone2007armv6320 x 4801.0 - 3.1.3 ×××××
iPhone 3G2008armv6320 x 4802.0 - 4.2.1 ××××
iPhone 3GS2009armv7320 x 4803.0 - 6.1.4 ×××
iPhone 4 (GSM)2010armv7640 x 960 *4.0 - 7.1.2 ×××
iPhone 4 (CDMA)2011armv7640 x 960 *4.2.5 - 7.1.2 ×××
iPhone 4S2011armv7640 x 960 *5.0 - ×××
iPhone 52012armv7s640 x 1136 *6.0 - ××××
iPhone 5c2013armv7s640 x 1136 *7.0 - ×××××
iPhone 5s2013arm64640 x 1136 *7.0 - ×××××
iPhone 62014arm64750 x 1334 *8.0 - ××××××
iPhone 6 plus2014arm641242 x 2208 **8.0 - ××××××
  
iPod touch2007armv6320 x 4801.1 - 3.1.3 ×××××
iPod touch (2nd)2008armv6320 x 4802.1.1 - 4.2.1 ×××××
iPod touch (3rd)2009armv7320 x 4803.1 - 5.1.1 ××××
iPod touch (4th)2010armv7640 x 960 *4.1 - 6.1.4 ××××
iPod touch (5th)2012armv7640 x 1136 *6.0 - ××××
  
iPad2010armv7768 x 10243.2 - 5.1.1 ××××
iPad 22011armv7768 x 10244.3 - ××
iPad (3rd)2012armv71536 x 2048 * 5.1 -×××
iPad (4th)2012armv7s1536 x 2048 * 6.0 -××××
iPad Air2013arm641536 x 2048 *7.0 - ×××××
iPad Air 22014arm641536 x 2048 *8.1 - ××××××
  
iPad mini2012armv7768 x 10246.0 - ××××
iPad mini Retina2013arm641536 x 2048 *7.0 - ×××××
iPad mini 32014arm641536 x 2048 *8.1 - ××××××

"CPU" とあるのは対応する CPU アーキテクチャを示しています。解像度で強調表記されているのは Retina ディスプレイを示しています。** は 3x 解像度です。

以下の iOS は特定のデバイスにのみ対応したバージョンになります。

3.2.*iPad (初代) 専用バージョン。
4.0 - 4.1iPad 未対応バージョン。
4.2.5 - 4.2.10iPhone 4 (CDMA) 専用バージョン。
参考
はてなブックマーク - iOS デバイス一覧表

スポンサーリンク

Safari で Reeder

[画像] Reeder on Safri

reederGoogle Reader を快適に利用できるアプリケーションです。

その reeder からインスパイアされて、似たルック & フィールを Chrome 上で実現する機能拡張が Reeder for Chrome (Unofficial) (以下、RFC) です。

残念ながら RFC の開発は継続されないことになりましたが、ソースは公開されています

RFC の最も肝となるルック & フィールは基本 css のみで実現されていて、Stylish を使えば、他のブラウザでも利用できそうです。

他に fork している人がいたので、その内容を確認しようと思っただけだったんですが、間違えて自ら fork してしまい、それをきっかけに中身を確認することに……。

  1. Stylish for Safari より Stylish の機能拡張をダウンロード・インストールします。
  2. ツールバー上にある「Stylish」ボタンから管理画面 (Manage) を開きます。
  3. 「Edit」を選ぶと新規スタイル編集画面が開きます。
    Title
    RFC
    CSS
    GitHub から CSS の内容をコピー
    Applies to
    "Regexp" を選択して、https?://www.google.*/reader/.*

その後、Google Reader を見ると Reeder のようなインタフェースに変わっていると思います。オススメは 3 カラム表示。

(Webkit に特化したスタイルを利用しているため) CSS の一部変更が必要になりますが、Firefox でもほぼ同様に Stylish から利用できます。

はてなブックマーク - Safari で Reeder

スポンサーリンク

バースデーカードを作ってみた

[写真] 今年の誕生日カード

先日、娘が誕生日を迎えました。

一応毎年カードみたいなものを用意していて、去年はカードの代わりに iPad で動く「誕生日アプリ」……マイクを使って息を吹きかけるとロウソクが消えるエフェクト付き……を作りました。

今年はどーしよーかなぁと思っていたんですが、なにやら最近少しだけ「ペーパークラフト」に興味を持っているようなので、ちょっとした工作をしてみることに……。

ざっと調べると、ペーパークラフトで文字が浮き出るような効果を出すために使える POPUP フォントなるものがいくつか見つかりました (Balloon Tales | Articles | Tutorial: Pop-Up LettersPop-Up Font | dafont.com)。

フォントを見てみると、専用フォントを使わなくても、ある程度線が太ければ利用できそうな感じだったので、自作してみることに。

ポイントは文字が浮き出たときに補助となる出っ張り部分。切り抜きのひな形を作るのはそれほど難しくありません。

[図] 紙半分の折り目にあたる部分に線を引く

まず、紙の半分、(印刷したときに) 折り目にあたる部分に直線を引きます。

[図] 折り目にまたがるように文字を置く

折り目をまたがるように文字を置きます。今回使ったのは Optima の Extra Bold 。個人的に気に入っているフォントで FloatyMemo のロゴにも使っています。

[図] 出っ張る長さを測る

折り目から文字の底にあたる部分の長さが、文字が浮き出てくる長さに相当します。

[図] 文字の上に出っ張り補助部を付ける

先に測った「折り目から文字底までの長さ」の分だけ文字の上に補助部をつけます。

[図] 他の文字も同じようにして補助をつける

他の文字にも同じようにして補助線を付けていきます。今回は文字を反転させています。これはカードの裏面に作ったひな形を印刷するためで、そうすることによって印刷した線が見えなくなります。

[図] 折り目になる部分

印刷した線は折り目以外は切り取ります。

  • 一番最初に引いた直線 (紙半分、カード自身の折り目にあたる)
  • 文字の底 (文字下部の折り目)
  • 文字の天で補助部と接する線 (文字上部の折り目)
  • 補助部の天 (出っ張りの折り目)

がそれぞれ折り目になります。このうち、「文字の天で補助部と接する線」以外は同じ方向に折ります。裏面に印刷するので、印刷面から見て「山折り」になって、「文字の天で補助部と接する線」だけは「谷折り」になります。

[写真] カードの裏面に印刷

少し厚手の紙に印刷します。印刷面がカードの裏面になります。

[写真] 線に沿って切っていきます

定規とカッターで丁寧に切っていきます。曲線部分はやや慎重に。折り目にあたる部分は山側になる方に軽く切れ込みを入れます。「文字の天で補助部と接する線」は表面が山側なので、そこだけは印刷面とは反対側から切り込みを入れます。

[写真] ゆっくり折っていきます

実のところ、折る作業が一番気を使うところかもしれません。写真だと分かりづらいですが、今回「T」の文字がやや失敗してしまって、横棒と縦棒のつなぎの部分が少し折れてしまいました。

はてなブックマーク - バースデーカードを作ってみた

スポンサーリンク

WWDC 2012 雑感

Retina ディスプレイが搭載された新しい MacBook Pro が発表されました。

15 インチ、薄型で 13 インチ MacBook Pro より軽い、DVD ドライブはおろか HDD ドライブもなし。メモリもオンボード直付けで後からの換装は不可能。…… MacBook Air 15 インチのような存在というと語弊があるでしょうか。

Retina ディスプレイ MacBook Pro では、Tunderbolt を二口搭載しつつ、さらに HDMI を搭載しています。つまり外部ディスプレイ用ポートが標準で 3 つあることに。

とりあえず、現在の仕様上では、外部ディスプレイ二つまではサポートしているようです (つまり本体ディスプレイと合わせて 3 つのディスプレイ表示)。

折角、グラフィックチップも Intel HD Graphics 4000 と NVIDIA GeForce GT 650M の二つ搭載していますし、将来的にはソフトウェアアップデートで 3 つの外部ディスプレイサポートなんてこともあるんでしょうか……。

今回の WWDC の発表では、何といっても iOS6 が気になります。さっそくベータをダウンロードして使っていて、色んな変化があって嬉しいやら (今後の対応を考えると) 辛いやら……。

NDA があるので、どこまで触れていいのか分からないのが悩みどころ。Apple から公にされている部分は触れても構わないと思うので、そこを中心に……。

大幅に更新された Map アプリは、もうただ驚き。まだベータ版っぽい動作で粗はいっぱいありますが、使っていて楽しいアプリであることには間違いないです。……前職だったので、ちょっと指摘するのが辛いところもあるんですが、ナビ関係のアプリ開発はこれから大変そうです……。標準添付だもんなぁ、これ。

メールアプリ、Apple 公式の Pull-to-Refresh が来ましたね。この挙動、WWDC でデモしたのかな。それとメールや設定アプリのスクリーンショットで気付いた方もいるかもしれませんが、バッテリー状態などを表示するステータスバーのアピアランスが変わっています。グレーじゃなくなって、バッテリーアイコンが単色に……。結構雰囲気が変わって見えますね。

Facebook 対応は結構嬉しい。私が利用するかどうかというよりも、おそらく Twitter 同様 Apple からフレームワークとしてサポートされると思うので。そうなると、Facebook 対応アプリを作りたいという時に開発負担が激減すると思います。

初代 iPad が対応していないのはちょっと残念。それより前にリリースされている iPhone 3GS が対応しているので余計。メモリ的に厳しいのかなと予想。やはり Siri が……。

WWDC 基調講演で発表された以外にもいろいろアップデート (Mac Pro とか、AirPort Express とか) があったようで、盛りだくさんな感じですね。

はてなブックマーク - WWDC 2012 雑感

スポンサーリンク

Objective-C / ARC で unsafe_unretained 利用時のインスタンス破棄タイミングについて

ここ最近のコーディングでは iOS5 SDK と同時に登場した ARC (Auto Reference Counting) を利用しています。

ARC の導入と注意点については、iOS 開発ブログ Natsu's note さんの一連の記事がとても参考になります。

C++ with boost に慣れた人なら、ARC はスマートポインタ (SmartPtr, AutoPtr) に近い動作をするという認識でよいと思います。

代入 (アサイン) 動作で参照カウンタが加算 (インクリメント) され、スコープを抜ける段階で release が呼ばるようなイメージで動作します。参照カウンタが 0 になった時点でオブジェクトが破棄されるのはこれまでの retain / release を使った従来の手法 MRC (Manual Retain-Release) と同様です。

明示的に retain / release を呼び出す必要がなくなり、巡回参照さえ気をつければ、メモリリークも軽減できる ARC はとても便利です。

そんな便利な ARC ですが、unsafe_unretained / weak 関連で不思議な動作をするのに気づいたので、忘れないようにメモしておきます。

Delegate 時の参照

[iOS5] ARC (Automatic Reference Counting) : Overview で触れられている通り、Cocoa プログラミングで多用される Delegate パターンでは「弱い参照 (weak reference)」を使って巡回参照によるメモリリークを防ぎます。

ただし、weak 修飾子は iOS5 以降でしか利用できません。iOS4 でも動作するアプリケーションにするためには、weak 修飾子を利用するところで unsafe_unretained 修飾子を使う必要があります。

unsafe_unretained 修飾子を使った場合、MRR で assign を利用したときと同様にアサインしたオブジェクトを適切なタイミングで nil 化してあげる必要があります。

しかしながら、unsafe_unretained 修飾子を利用する場合、ある条件下でオブジェクトが不用意に解放されてしまう場合があります。この場合、適切と思われる箇所で nil 化していても EXC_BAD_ACCESS の要因になりうるので注意が必要です。

多段 Delegate

さて、その「ある条件」について考察していきます。

以下は私が見つけたパターンですが、他にも同様なケースがあるかもしれません。

  1. ある Object A が Object B を作成し、その Delegate として動作します。

  2. Object B は内部で Object C を作成していて、その Delegate として動作していて、Object C からの通知を起点に Object B から Object A にメッセージが送信されます。

  3. Object A は Object B の Delegate メッセージを受け取り次第、Object B を利用しないので、Object B を破棄します。

文章にすると若干ややこしい感じがしますが、例えば、

ネットワーク越しのデータを処理するあるクラス (Object B) は内部で NSURLConnection (Object C) を利用していて、データ受信終了を起点に Object B でデータ処理を行い、Object A に通知する

というケースなどが該当します。

[図]多段 Delegate の基本パターンダイアグラム

コードで表現すると、

@class SampleClassA;
@class SampleClassB;
@class SampleClassC;

@protocol SampleDelegateB <NSObject>

- (void)callFromClassB:(SampleClassB *)object;

@end

@protocol SampleDelegateC <NSObject>

- (void)callFromClassC:(SampleClassC *)object;

@end

#pragma mark -

@interface SampleClassA : NSObject <SampleDelegateB>

@end

@interface SampleClassB : NSObject <SampleDelegateC>

@property (nonatomic, unsafe_unretained) id<SampleDelegateB> delegate;

@end

@interface SampleClassC : NSObject

@property (nonatomic, unsafe_unretained) id<SampleDelegateC> delegate;

@end

というような形で、SampleClassB では SampleDelegateC のデリゲートメソッド callFromClassC: 内で SampleDelegateB デリゲートメッセージを通知します。

- (void)callFromClassC:(SampleClassC *)object
{
  NSLog(@"  -> started  [%p] with '%@'",self,self.message);
  [self.delegate callFromClassB:self];
  NSLog(@"  -> endded   [%p] with '%@'",self,self.message);
}

つまるところ、オブジェクト C からのメッセージをフォワードするような感じのイメージ。

多段 Delegate のワナ

この形だけでは特になんてことはないのですが、

Object A は Object B の Delegate メッセージを受け取り次第、Object B を利用しないので、Object B を破棄します。

という条件が加わると、オブジェクトが破棄されるタイミングが実装によって変わってきます。

  • weak 参照を利用している

  • unsafe_unretained 参照を使っていて、プロパティ (メソッド) を通してデリゲートにアクセスしている

  • unsafe_unretained 参照を使っていて、メンバ変数でデリゲートにアクセスしている

オブジェクトが破棄されるタイミングが weak 参照をつかっているか、unsafe_unretained 参照を使っているか……さらにはプロパティを使っているかなどの条件で変わってきます。

サンプルコードを github に上げたので、それを元に挙動を確認することができます。

以下の実行結果は、Xcode 4.3 / iOS5 SDK を利用して行なったものです。

weak 参照を利用

SBSampleDelegate.h において

  • kUsingWeak 1
  • kAsseccingViaProperty 0
  • kUsingRetainAutoreleaseHack 0

のように設定した場合。

[A]===> initialized [0x6a67830]
[C]  -> initialized [0xXXXXXXX]
[B]  -> initialized [0xXXXXXXX] with 'msg0'
[C]  -> started     [0xXXXXXXX]
[B]  -> started     [0xXXXXXXX] with 'msg0'
[A]===> called      [0xXXXXXXX]
[A]===> removed     [0xXXXXXXX]
[B]  -> endded      [0xXXXXXXX] with 'msg0'
[C]  -> ended       [0xXXXXXXX]
[B]  -> destroyed   [0xXXXXXXX] with 'msg0'
[C]  -> destroyed   [0xXXXXXXX]

C → B と作成され、逆に B → C と破棄されています。期待通りの動作と言えそうです。

unsafe_unretained 参照を使っていて、プロパティ (メソッド) を通してデリゲートにアクセス

SBSampleDelegate.h において

  • kUsingWeak 0
  • kAsseccingViaProperty 1
  • kUsingRetainAutoreleaseHack 0

のように設定した場合。

[A]===> initialized [0xXXXXXXX]
[C]  -> initialized [0xXXXXXXX]
[B]  -> initialized [0xXXXXXXX] with 'msg0'
[C]  -> started     [0xXXXXXXX]
[B]  -> started     [0xXXXXXXX] with 'msg0'
[A]===> called      [0xXXXXXXX]
[A]===> removed     [0xXXXXXXX]
[B]  -> endded      [0xXXXXXXX] with 'msg0'
[B]  -> destroyed   [0xXXXXXXX] with 'msg0'
[C]  -> ended       [0xXXXXXXX]
[C]  -> destroyed   [0xXXXXXXX]

C → B と作成され、逆に B → C と破棄されていますが、分かるでしょうか、[B] -> destroyed[C] -> ended の呼び出される順番が逆になっています。

SampleClassC からデリゲート B を呼び出しているメソッド callDelegate のスコープにまだいる最中に SampleClassC のデリゲートである SampleClassB のインスタンスが破棄されています。

これですぐに問題になるケースはぱっと思いつきませんが、ちょっとだけ不安な感じ。

unsafe_unretained 参照を使っていて、メンバ変数でデリゲートにアクセス

SBSampleDelegate.h において

  • kUsingWeak 0
  • kAsseccingViaProperty 0
  • kUsingRetainAutoreleaseHack 0

のように設定した場合。

[A]===> initialized [0xXXXXXXX]
[C]  -> initialized [0xXXXXXXX]
[B]  -> initialized [0xXXXXXXX] with 'msg0'
[C]  -> started     [0xXXXXXXX]
[B]  -> started     [0xXXXXXXX] with 'msg0'
[A]===> called      [0xXXXXXXX]
[A]===> removed     [0xXXXXXXX]
[B]  -> destroyed   [0xXXXXXXX] with 'msg0'
[B]  -> endded      [0xXXXXXXX] with '(null)'
[C]  -> ended       [0xXXXXXXX]
[C]  -> destroyed   [0xXXXXXXX]

明らかにおかしい挙動になります。

まだ C からのデリゲート callFromClassC: のスコープにいるのにも関わらず、dealloc が呼び出されています。

SampleClassB のインスタンスが破棄された後、callFromClassC: のメンバである mMessage にアクセスしているので、(null) と表示されています。場合によっては EXC_BAD_ACCESS の要因になります。

retain-autorelease ハック

という訳で unsafe_unretained 参照を利用すると、weak 参照とは異なった挙動になってしまいます。

これは MRR で assign を利用した場合でも起こりうる現象です。MRR ではこれに対して、

[[obj retain] autorelease]

retain と autorelease を併用することで、当該オブジェクトを autorelease プールに登録して、少なくともスコープ内はオブジェクトが破棄されないようにすることができました。

ご承知の通り、ARC では retain / autorelease メソッドの呼び出し自体が禁止されているので、同じハックは利用できません。

ただ、ローカルな変数に対しては、__autorelesing 修飾子を利用することによって autorelease プールを利用することを明示できます。

__autorelasing id temp = obj;

これでスコープ内では temp を利用すると、インスタンス obj に対して retain-autorelease で呼び出したのと同じような効果が得られます。

SBSampleDelegate.h において

  • kUsingWeak 0
  • kAsseccingViaProperty 0
  • kUsingRetainAutoreleaseHack 1

のように設定した場合、SampleClassA において retain-autorelease ハックを利用します。

[A]===> initialized [0xXXXXXXX]
[C]  -> initialized [0xXXXXXXX]
[B]  -> initialized [0xXXXXXXX] with 'msg0'
[C]  -> started     [0xXXXXXXX]
[B]  -> started     [0xXXXXXXX] with 'msg0'
[A]===> called      [0xXXXXXXX]
[A]===> removed     [0xXXXXXXX]
[B]  -> endded      [0xXXXXXXX] with 'msg0'
[C]  -> ended       [0xXXXXXXX]
[B]  -> destroyed   [0xXXXXXXX] with 'msg0'
[C]  -> destroyed   [0xXXXXXXX]

weak 参照と同様に C → B と作成され、逆に B → C と破棄されています。

ログでは同じように見えていますが、こちらの実装では、B は autorelease プールのタイミングで破棄されているので、内部的には異なる挙動になっています。ただ、不用意な破棄がなくなり、アクセスバイオレーションはなくなります。

はてなブックマーク - Objective-C / ARC で unsafe_unretained 利用時のインスタンス破棄タイミングについて

スポンサーリンク

SBPullToRefreshHeaderView - 「引っ張って更新」を再実装してみる

HMDT さんから開発者向け電子書籍がリリースされています ([本] HMDT JOURNAL 創刊 | Cocoaの日々情報局 経由)。

早速、Vol.001 と Vol.002 を購入してみました。木下さんらしい読みやすい文体で、かなり丁寧に書かれています。

……特定の連載記事だけをバラで購入できたら嬉しいなぁ……なんて。ともあれ、今後の展開が楽しみです。

EGOTableViewPullRefresh

さて、この HMDT JOURNAL Vol.001 で紹介されている EGOTableViewPullRefresh は、いわゆる「引っ張って更新」を実現するクラスで、Facebook 謹製のライブラリでも採用されていたりする有名なライブラリです。

組み込みも簡単で、コードも分かりやすく記述されているライブラリなのですが、導入にあたってコントローラ側で UIScrollViewDelegate のメッセージをフォワードする必要がある点がちょっと不満。

例えば、UIButton ではボタンのハイライトのためにタッチイベントをコントローラ側からフォワードしなくても、ボタン側で勝手に処理してくれるように、EGOTableViewPullRefresh もスクロールイベントを勝手に処理してくれたらなぁと思うわけです。

SBPullToRefreshHeaderView - yet another "pull-to-refresh"

……そこで自分で「引っ張って更新」するクラス SBPullToRefreshHeaderView を自作してみました。

[図] SBPullToRefreshHeaderView の実装例

ARC 対応で __weak 修飾子を使っているので、iOS5 以降でお使いいただけます。

他に EGOTableViewPullRefresh から微妙に変わっている部分に「離して更新」の時にリロード用画像を使っています。OS X 向け Twitter アプリケーションのような感じ。

サンプルデモのコードにある通り、コントローラ側では SBPullToRefreshHeaderView の初期化メソッドにターゲットとなるスクロールビューを渡すと、あとは SBPullToRefreshHeaderView 側でよしなにしてくれます……はずです。

mRefreshHeaderView = [[SBPullToRefreshHeaderView alloc] initOnScrollView:self.tableView
                                                            withDelegate:self];

デリゲート SBPullToRefreshHeaderViewDelegate のメソッドはふたつ。

@protocol SBPullToRefreshHeaderViewDelegate <NSObject>

/// 「引っ張り更新」の発動 (ユーザが更新するためにスクロールビューを離した) を通知します。
/// @param headerView - 関連する SBPullToRefreshHeaderView のインスタンス
- (void)didTriggerRefresh:(SBPullToRefreshHeaderView *)headerView;

/// ターゲットが「ローディング」状態がどうかを確認します。
/// @param headerView - 関連する SBPullToRefreshHeaderView のインスタンス
/// @return ローディング状態にある場合、YES をそうでない場合 NO を返します
- (BOOL)isRefreshStillProcessing:(SBPullToRefreshHeaderView *)headerView;

@end

コントローラ側では基本的にはこのふたつのデリゲートメソッドを実装して、ローディングが終了した後に「resetView:」メソッドを送信します。

SBPullToRefreshHeaderView の実装

SBPullToRefreshHeaderView ではスクロールイベントを処理するために KVO (Key-Value Observing) を使っています。

スクロールが発生すると、UIScrollViewcontentOffset が変化することに着目して、そこでスクロール時に処理する内容を記述しています。

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
  if (object == mScrollView &&
      [keyPath isEqual:@"contentOffset"])
  {
    [self scrollViewDidScroll:mScrollView];
    if (mIsDragging != mScrollView.isDragging)
    {
      if (!mScrollView.isDragging)
      {
        [self stopDragging];
      }
      mIsDragging = mScrollView.isDragging;
    }
  }
}

ユーザーがターゲットのスクロールビューから指を離したかどうかの判定もここで行っています。スクロールの変化で判定しているので、実際のタッチリリースとは異なるタイミングになりますが、動作させてみた感じ特に違和はない感じ。

オブザーブを開始・終了するタイミングが少しハック的な実装になっています。

……というのもオブザーブを開始した時点で参照カウンタがインクリメントされてしまうため、どこか適当なタイミングでオブザーブを終了してあげないといつまで経ってもオブジェクトが解放されなくなってしまいます。

SBPullToRefreshHeaderView の実装では、ターゲットとなっているスクロールビューの子ビューとして追加されたときにオブザーブを開始、親ビューがターゲットから外れた時点でオブザーブを終了するようにします。

- (void)didMoveToSuperview
{
  if (self.superview == mScrollView)
  { // The view has been added into the target scroll view so it starts 
    // observing contentOffset changes.
    [mScrollView addObserver:self 
                  forKeyPath:@"contentOffset" 
                     options:NSKeyValueObservingOptionNew 
                     context:nil];
  }
  else
  { // The view has been removed from the target scroll view so it stops 
    // observing contentOffset changes.
    [mScrollView removeObserver:self
                     forKeyPath:@"contentOffset"];
  }
}

UIView の 「didMoveToSuperview」メソッドで親ビューの変化をキャッチできるので、そこでオブザーブの開始・終了を制御しています。

GitHub にサンプルデモと一緒に置いてみましたので、もしよろしければお使いください (MIT-License)。

はてなブックマーク - SBPullToRefreshHeaderView - 「引っ張って更新」を再実装してみる

スポンサーリンク

Xcode 4.3 リリース

二月になってしまいましたが、2012 年もよろしくお願いします。

Xcode 4.3 がリリースされました。

Mac App Store との親和性を高めるため、Xcode 4.3 からはインストール先が変更されています。

  • Xcode 4.2 まで : /Developer
  • Xcode 4.3 から : /Applications

インストール方法も変わりました。Xcode 4.2 までは何らかの方法で Xcode のインストーラを起動する必要がありました。

Xcode 4.2 では Mac App Store からダウンロードされるものは「Xcode Install」で Xcode そのものではありませんでした。

Xcode 4.3 からはインストーラは目に見えては存在しません。App Store からダウンロードして、そのまま他のアプリケーションと同じように起動するだけです。

Xcode 4.3 はインストールされる場所が最大の違いで、機能的な違いはほとんどない印象です。

Xcode に付録されるユーティリティ

Xcode 4.2 まで /Developer/Applications の中にあった Instruments や Icon Composer, FileMerge といったユーティリティは Xcode 4.3 から Xcode アプリケーション内に内包されています。

Dashcode, Quatz Compozer などこれまで Xcode に付録 (?) として付いてきたいくつかのアプリケーションは Xcode 4.3 には含まれていません。

developer.apple.comダウンロードセンターから別途ダウンロードする必要があります。

  • Dashcode → Dashcode for Xcode - February 2012
  • Quartz Composer → Graphics Tools for Xcode - February 2012

Instruments など Xcode 4.3 に内包されているアプリケーションを起動するには Xcode を立ち上げて、Xcode メニューより「Open Developer Tool」を利用します。

[図] デベロッパツールメニュー。

Xcode に内包されているアプリケーションでも起動させた状態で Dock に保持するようにすれば、Dock から (Xcode を通さずに) 立ち上げることができます。Xcode に内包されているアプリケーションは Spotlight では拾ってくれないようです。

コマンドラインツール

Xcode 4.3 にはもちろんコンパイラは付いてきますが、Xcode 4.2 まで /Developer/usr/bin に含まれていたいくつかのツールは含まれていません。前述のダウンロードセンターからダウンロードするか、設定画面の「Downloads」より「Command Line Tools」をダウンロードします。

[図] Xcode 4.3 設定内のダウンロード。

Xcode 4.3 からの仕様変更により OS X のパッケージマネージャ Homebrew は Developer Preview の時には動作しなくなってしまいましたが、Command Line Tools をちゃんと入れれば、大丈夫な様子。

以前の Xcode との共存

Xcode 4.3 はこれまでの Xcode と同様、以前のバージョンの Xcode と共存が可能です。一番最初に Xcode 4.3 を立ち上げたときにインストールされている Xcode をゴミ箱に移動するかどうか聞かれます。

[図] Xcode 4.3 最初の起動時に表示されるダイアログ。

該当するディレクトリを単にゴミ箱に移すだけのようで、/Developer/Library/uninstall-developer-folder は実行されない様子。

ヘルプでは「(古い Xcode は) 後からでもいつでもゴミ箱に入れられます」とあって、uninstall-developer-folder の実行には触れられていません。ゴミ箱に移して削除すればアンインストールされるんでしょうか。

はてなブックマーク - Xcode 4.3 リリース

スポンサーリンク

転職しました

先日、私がニュージーランドに移住して初めて就職し、八年間勤めた会社 (ポータブルナビゲーションデバイス、いわゆる「カーナビ」のソフトウェア開発) を退職しました。

[写真]退職の際にもらったカード。皆からの寄せ書きです。

退職時のメールは以下の通り。

Dear All,

It's my last working day here at <company name>.
I would like to thank you all for your great support.

I have been working here over 8 years; it's long long and really exciting journey.
I will miss all such comfortable environment - great people, great products, and walking distance from home.

Please keep in touch.

I can be reached :

via email : <email address>
on LinkedIn : <LinkedIn url>
on Facebook : <Facebook url>
on Skype : <Skype account>
via mobile : <mobile phone number>

I wish you all the best for the future.

Best regards,
Takuya

およそ九年前にもニュージーランド移住にあたって、日本で五年間勤めた某大手電機メーカーを辞めました。その時と比べると私の中で感じる「重み」が違います。

九年前、日本で退職したときはニュージーランド移住がまず念頭にあり、ほぼ何もない状態からスタートする、いわば「リセット」的な意味合いが多分にありました。

不安も一杯でしたが、失うものもないという意識もあって「すっきり」「心機一転」という気持ちが強かったと思います。世間知らずであまり後先考えていなかったというのもあったと思います。

世間知らずなのは、今も大して変わっていない気もしますが。

八年前、ソフトウェアエンジニアとして就職。

シニアソフトウェアエンジニアとしてテクニカルリーダーなどを経験し、最終的にはソフトウェアチームリーダーとして、ソフトウェア開発ばかりでなくマネージメントも含め、たくさんの貴重な経験を積むことができました。

会社自体も、山あり谷あり。

飛ぶ鳥を落とす勢いの時……新社屋落成セレモニーに時の首相が訪問しました……もあれば、大規模なリストラが敢行されたこと……人数削減のため同ポジションの人の間で点数をつけて上位数名だけ残る……もありました。

そのような過程を経た八年間。

職場はとても快適で、上司・部下に限らず皆からの信頼も感じていて、自信もつきました。……正直なところ「去りがたい」「怖い」という気持ちも少なからずあります。

一方で、あまりにひとつの会社に依存しすぎるのもリスクとも思っていたのも確かです。

ポータブルナビゲーションデバイスのソフトウェア開発がどこまで「保つ」ものなのかという面の不安もあります。

八年間の経験を通して、技術面でもコミュニュケーション面でも英語圏で十分に通用するという自信はつきましたが、一社でのみの経験で、それが他所でも通用する保証はありません。

色んなオプションを検討した末、今回転職に踏み切りました。

不安がないと言えば嘘になりますが、全く異なる分野でのソフトウェア開発ということで新鮮な気分もあります。

自分のスキルを生かすという点ではこれまでと変わりありません。とりあえず、頑張ってみようと思います。

はてなブックマーク - 転職しました

スポンサーリンク

ハーフマラソンに挑戦してみた

先日行われたオークランドマラソンにて、ハーフマラソン完走しました→結果は 1 時間 42 分

目標としていたタイムは 1 時間 45 分で、それを上回ることができました。初ハーフマラソンとしては上出来だと自画自賛。

  1. きっかけ
  2. 年始目標
  3. トレーニング
  4. オークランドマラソン

きっかけ

もともと身体が小さくて筋力がない方なのですが、それに加え 30 歳過ぎまで喫煙をしていたせいもあり、全体的な持久力の低下も少し心配していました。

それで、二年前の誕生日頃から、体力づくりというか体力維持を目的としてジョギングを始めました。

仕事が終わってから夕食の前に自宅の周辺 3km ほどのコースを走ります。

理想的には毎日走りたいところですが、仕事や天気の状況次第で週に二、三日ぐらい走れるという感じのペース。

とにかく続けることが目標という感じで始めたのですが、ある程度の強制力がないと続かないという嫁さんの進言で、ビーチシリーズという地元のローカルレースにも参加しはじめました。

ビーチシリーズは 11 月から翌年 3 月にかけて毎週火曜日、地元のビーチで行われるローカルレースです。ランの他にもスイムやパドルボードなどの種目があります。

ビーチシリーズのランは 5km。文字通り浜辺を走ります。潮の満ち引きの加減でコースの状態や長さが安定していないのが難点ですが、レースという形式で走るのが刺激になります。

参加し始めた当初は 5km で 25 分程度だったのですが、段々と慣れてきたせいか、昨年度は 21 分程度まで縮めることができました。

年始目標

とりあえず 5km 程度ならばそこそこ走れる、という自信がついてきたので、もう少し長い距離に挑戦してみようと思いたったのが、今年の始め。

長距離ランの代表格はなんと言っても「マラソン」になると思いますが、いきなりマラソンはキツいかもと思い、「今年中にハーフマラソンを完走する」という目標を立てました。

最初は地元で行われる North Shore Marathon に参加しようかなと思っていたのですが、たまたま会社の同僚に話したところ、「おぉ、そいつはグッドアイデアだ。俺も参加しよう」ということになりました。

折角なら一番大きな大会にしようということでオークランドマラソンに参加することに……。

オークランドマラソンの方が開催時期が二ヶ月遅く、その分、準備期間を取れるという要因もありました。

もちろん完走が目標で、できれば二時間を切るタイムで完走したいというのが、とりあえず参加を決めた当初の目標。

トレーニング

会社の同僚も巻き込んで、いよいよ後に引けなくなりました。

五月頃から普段 (3km) よりも長めの距離を走れるように意識し始めます。

ざっくりトレーニングの方法を調べてみましたが、単純に長い距離走ればよいというものではないみたいで、短距離ダッシュなども取り入れる必要がある感じです。

そこで実際、短距離ダッシュもやってみたのですが、そうするといかにも「練習」っぽくなってしまい、長続きしそうにありません。

あくまでも長く続けることが第一なので、トレーニング方法を参考にしつつ、自分なりに以下のように決めました。

平日
短い距離 (3km) を早めのペース (1km 4 分 30 秒を切るペース)。
休日
長い距離 (10km 以上) をゆっくりペース。余裕があれば、さらに中距離 (5km 〜 8km) を別の日に走る。

平日は 30 分未満、休日は 1 時間以上走るという感じです。

これまで 10km を超える長距離は走ったことがありませんでしたが、ここ二年間走っていたおかげで 1km 5 分ペースであれば、結構走れる感触。

ただ、実際走ってみると……

  • 最初の 4km が少しキツい。おそらくウォームアップ不足。
  • 10km 過ぎたあたりから膝に負担を感じるようになる。
  • 15km 過ぎたあたりから股関節に負担を感じるようになる。

心肺よりもむしろ関節への負担が想像以上にありました。スクワットやストレッチなどを都度きちんとやるようにして、膝や股関節への負担に備えます。

ストレッチなどは走る前にはもちろんですが、家でぼーっとしているときやプリンを作っている合間などスキマ時間も利用します……といえ、無理にしているわけではなく、気づいたら都度ストレッチなどをするという感じ。とにかく練習っぽくせずに「日常の延長」でできれば、という感覚で。

同僚に誘われて、dailymile というオンラインサービスにも登録してみました。走った記録は手元にも残していましたが、dailymile ではペース計算や週毎・月毎の集計などを自動でやってくれますし、 facebook との連携もあったりして、便利なツールです。

オークランドマラソン

九月・十月のトレーニングの内容から、1km 5 分のペースを基本にして、21km x 5 分 = 105 分 = 1 時間 45 分を最終的な目標タイムにします。

オークランドマラソンは交通機関への影響を配慮してか、早朝にスタートするのが特徴です。

[写真]スタート周辺の様子

日が上がる前からスタート地点である「デボンポート」に集合します。早朝なので、公共の交通機関はなくて、臨時フェリーと臨時バスが出ます。

最寄りのバス停まで 4km 弱もの距離があるのがちょっとやっかいでしたけど、結果的にはちょうどよいウォーミングアップになりました。

[写真]日の出をスタート地点から望む

フルマラソンとハーフマラソンは同じ地点からスタートします。フルマラソンが先にスタートして、その後ハーフがスタート。フルマラソンのスタート後、ハーフのスタートを待っている間に日の出を迎えました。

[写真]スタートゲート

スタートゲート。「Elite」のカンバンが見えるでしょうか。速い人はゲート前に並んで遅い人はゲートから離れた位置でスタートします。人が並び始める前にちょっと様子見。

[写真]ノースコートにて

スタート地点からおよそ 10km あたりで嫁さんと娘が応援してくれました。自作の横断幕を持つ娘と走り過ぎる私 (後ろ姿)。まだこの頃は余裕が……。

[写真]ハーバーブリッジを登る

スタート地点からおよそ 15km あたり、オークランドマラソンの (フルマラソンなら前半の) クライマックスとも言える「ハーバーブリッジ」に差し掛かります。

ここは上り始め。ここからおよそ 1km 弱ほどそこそこキツい上り坂……。

[写真]頂上 (?) が見えてくる

はためくニュージーランドの国旗。ちょっと旗の真下がブリッジの頂上にあたります。

[写真]ハーバーブリッジからシティを望む

ハーバーブリッジは通常、車でしか通行できず、また基本的に停まることができません。車から降りて渡る機会などそうそうないので、ハーバーブリッジを渡っているときには写真は撮ってやろうと思ってました。

ハーバーブリッジでの写真は走りながら撮っています。幸い十分明るかったので、思ったよりブレもなく撮れました。

[写真]ゴール地点

続々とゴール。ゴール地点には給水だけでなく、バナナの配布もしてました。風船をつけた人はペースメーカー。

[写真]ラストスパート

私もなんとかゴール。

オークランドマラソンはフルマラソン前半部分 (つまり、ハーフマラソン全コース) のコースの起伏が激しいのが特徴で、ハーバーブリッジがそのクライマックスになるんですが、それが終わった後がキツかったです。起伏での消耗が起伏が終わった途端にどっと来る感じ。

ハーフを無事に完走し、次はフル?とも聞かれたんですが、フルマラソンを走るにはもう少しトレーニングが必要かも。

ちなみにその日の午後は爆睡。どうにか次の日、会社には出勤することができましたが……。

はてなブックマーク - ハーフマラソンに挑戦してみた

スポンサーリンク

2/24