2014/01/01

謹賀新年

0 コメント この投稿へのリンク
このエントリーをはてなブックマークに追加
新年明けましてお目出度う御座います。

旧年中は大変お世話になりました。このブログを読んでくださっている皆様、TwitterをFollowしてくださっている皆様、その他、お世話になった皆様へ、深く感謝いたします。本当に有難うございました。

今年はここ数年間続けてきた業務が一区切りとなり、新たな展開を迎えそうです。今からワクワクしています。

昨年末は、数年越しで床へと積まれてしまった書籍や、戸棚へ押し込まれたCD類を処分することができ、ようやく足の踏み場を確保出来ました。

今年は、物理的なモノだけでなく、放置してしまっているデジタル的なモノも整理していけたら良いな、と思っています。

今年が皆様にとって、素晴らしい一年となりますよう、お祈り申し上げます。

本年も宜しくお願い致します。

2013/12/28

VMWare FusionのSCSIドライバを64bit環境用へ変更する

0 コメント この投稿へのリンク
このエントリーをはてなブックマークに追加
今までVMWare Fusion(v6.0.2)上で32bit版Windowsを動作させていましたが、64bit Windowsへアップグレードすることにしました。

OSの再インストールになりますが、OSアップグレード処理中、旧来のOSがインストールされたディスクへのアクセスが発生するため、新規VMを作成するのではなく、旧環境を更新する必要があります。

環境の変更は、メニューにある「Virtual Machine > Settings....」から「Genral」を選び、「OS」の横にあるプルダウンメニューから適切なOSを選択することで行います。

この変更を行ったVMを起動させようとしたところ、

The BusLogic SCSI adapter is not supported for 64-bit guests.

のエラーメッセージが表示され、起動できません。

この問題を修正するには、.vmx ファイルの書き換えが必要です。VMWare 社の Knowledge Base では1020879として公開されています。

.vmxファイルはVM一式と共に保存されています。

VMの保存場所は、VMWare Fusion のメニューに有る「Virtual Machine Library」から、右クリックなどでショートカットメニューを開くと表示される「Show in Finder」から確認できます。

Finder上では、単一ファイルとして表示されるため、同じくショートカットメニューの
「Show Package Contents」を選ぶと、その中に.vmxファイルが表示されます。

この中から該当するSCSIデバイス番号を親に持つ、virtualDevキーを探します。
例えばSCSIデバイス0のドライバを書き換えるにはscsi0.virtualDevを探します。

この値が"buslogic"になっている場合には、それを"lsilogic"へ書き換えます。

scsi0.virtualDev = "lsilogic"

もしこのキーが.vmxファイルへ存在しない場合には、適当な場所へ追加します。

これで、VMを64bit環境で起動できるようになります。

2013/12/02

iOS の task completion について

0 コメント この投稿へのリンク
このエントリーをはてなブックマークに追加
TMPTaskCompletionManagerの公開に伴い、task completionについてまとめてみます。

task completion は iOS4 で導入されたマルチタスク処理方式の一つです。アプリがバックグラウンドモードへ入った後も、実行中の処理を継続したいときに使います。実行可能時間は、iOS6までは最長10分間。iOS7では最長3分間へ短縮されました。

バックグラウンドでの実行要求は、
- [UIApplication beginBackgroundTaskWithExpirationHandler:]
で行います。要求は何度でも可能です。
処理が終了したなど、バックグラウンドでの実行が不要になった場合には、
- [UIApplication endBackgroundTask:]
を呼び出さなければなりません。このメソッドを呼び出すか、規定時間が経過した場合、アプリケーションはバックグラウンド処理を終了し、サスペンド状態へ入ります。

StackOverflowでも言及されているように、beginBackgroundTaskWithExpirationHandler:は、名前に「begin」と付いているものの、実際にはバックグラウンド処理を開始しません。このメソッドは、OSに対し、バックグラウンドでの処理継続を要求するために使います。

beginBackgroundTaskWithExpirationHandler:が呼び出される毎に、OSはその回数を記録します(動作可能時間は初回要求時から増えません)。この数値が1以上である場合、OSは、アプリがバックグラウンド処理を要求していると判断します。この回数は、endBackgroundTask:で減算されます。0になった時点で、OSはアプリケーションはバックグラウンド処理を望んでいないと判断します。メモリ管理のリファレンスカウントと同じ原理です。

言い換えれば、endBackgroundTask:を呼び出すまで、アプリケーションはバックグラウンド処理を要求し続けていることになります。例えば、アプリがフォアグラウンドへ復帰するなど、バックグラウンド処理が不要になった場合には、明示的にendBackgroundTask:を呼びださなければなりません。

Appleが公開しているiOS App Programming GuideExecuting a Finite-Length Task in the Backgroundでは言及されていないためか、「Cocoaの日々」「[iOS] バックグラウンド実行見本(Task Completion)」などを除いて、あまりフォアグラウンド復帰時の処理に関し、言及していないように感じています。

この動作を確認するために TaskCompletionSample を作成しました。

https://github.com/n-miyo/TaskCompletionSample

このアプリはアプリケーションバッジを1秒ごとに増加させます。beginBackgroundTaskWithExpirationHandler:の実行はviewDidLoadで行われ、endBackgroundTask:は実行されません。

アプリをバックグラウンドへ落とすと、バッジの増加を通じてバックグラウンド処理を確認できます。アプリを一度フォアグラウンドへ復帰させ、再度バックグラウンドへ遷移させてみます。この処理の過程では新たにbeginBackgroundTaskWithExpirationHandler:を呼び出していませんが、アプリはバックグラウンド実行を継続可能です。

画面の「clear at 'didBecomeActive'」スイッチをONにすると、- [AppDelegate applicationDidBecomeActive:]実行時、endBackgroundTask:を実行するようになります。
この状態で、一度アプリをバックグラウンドへ遷移させ、再度フォアグラウンドへ遷移させた後、再度アプリをbeginBackgroundTaskWithExpirationHandler:へ移行させると、endBackgroundTask:との呼び出し回数が釣り合い、以後バックグラウンドでの実行は行われません。

さて、バックグラウンド処理を要求する場合、時間切れ時に実行されるタスクを登録し、その中でもendBackgroundTask:を実行する必要があります。これらは定形で書けますが、毎回書くのは面倒なものです。

また、複数のタスクをバックグラウンド登録した場合、それらをフォアグラウンド復帰のタイミングで一斉にキャンセルするには、すべてのタスクIDを管理しなければなりません。

これらの比較的定形でありながら、毎回書くのが面倒になるコードをまとめたものが、先に公開した TMPTaskCompletionManagerになります。使い方などは、「iOS の task completion をサポートする TMPTaskCompletionManager を公開しました」を御覧ください。

ご意見などお待ちしております。