SimpleBoxes

ここ三、四年で利用している (利用した) ワイヤレスマウスの個人的まとめ

[写真] 所有マウス

左上から時計回りに

Logitech (ロジクール) と Microsoft のマウスしかありませんが、特にメーカー指定で選り好みしている訳ではなくて、日本だと手軽に手に入るであろうエレコム、バッファロー、サンワサプライなどのメーカーは私の在住しているニュージーランドでは手に入りづらいのが一番の理由です。

V470 Cordless Laser Mouse を利用してからというもの、基本的には何らかのワイヤレスマウスを利用しています。

MacBook Pro 13 (Early 2011) を購入してからはトラックパッドも以前よりも利用するようになりましたが、それでもやはりメインのポインティングデバイスはマウスです。

V470 Cordless Laser Mouse は四、五年前ぐらいに挙動不審になってしまい、それ以降いくつかのワイヤレスマウスを利用してきました。

ワイヤレスマウスに対しての基本的な利用基準は、あまり変わっていなくて

  • Bluetooth 対応
  • 光学式あるいはレーザー式のトラッキング
  • スクロールホイール
  • 2 ボタン以上のサポート

ボタンの数に特別なこだわりはありませんが、Mission Control の利用を考慮すると 3 ボタンは欲しいところ (左クリック・右クリック・センターボタン)。

多機能なマウスだと 4 つ以上のボタンがあることもありますが、あっても使うことがないので、あってもなくても気にしません (それがあることで価格が高くなるのであれば、ない方がいい)。

2016.08 現在のメインマウス

とりあえず、まず最初に現在メインとして利用しているマウスを先に言っておくと……

前者は Macbook Pro 13 (Early 2011) 用に、後者は会社で利用している Macbook Pro 15 (Mid 2015) 用に利用しています。

Apple Magic Mouse

まず、基本的なところで Apple からリリースされている Magic Mouse と Magic Trackpad

現在だと Magic Mouse 2 に置き換えられているようですが、使い勝手は従来の Magic Mouse とほぼ変わらないようです。

Apple 製なので、Macbook との相性は良いと思います。

ボタンやホイールの代わりにトラックパッドを組み込んだようなマウスで、マウス表面がタッチセンサーになっています。二本指ジェスチャーなどで Mission Control を利用できたりします。

無線形式Bluetooth
トラッキングレーザー
大きさ(縦) 11.35 cm x (横) 5.71 cm x (高) 2.16 cm
重さ55 g (電池なし)
106 g (電池あり)
99 g (Magic Mouse 2)
電池寿命?

前後左右対称な形状で、突起物などもないため、前後が逆さまになっていた時、触っただけでは分かりません。マウスを動かしてみるか、Apple ロゴの向きや位置で確認する必要があります。

平べったい形状のため、利用中は常に手のひらとマウスの間に空間ができるような形になります。私はそれが少し気になって、メインマウスとしては利用できませんでした。

ちなみに Magic Mouse と Magic Trackpad は、前職の会社支給での利用なので、現在所有していません。

Apple Magic Trackpad

別記事でも触れたとおり、ユニボディな MacBook に搭載されたトラックパッドは、それまでのトラックパッドとは一線を画すと言っても過言ではないほど使い勝手が向上されています。

それを単独な形で切り出したのが Magic Trackpad で、使い勝手はほぼ同等。MacBook に搭載されているものより一回り大きいので、その分向上しているとも言って良いかもしれません。

無線形式Bluetooth
大きさ(縦) 11.0 cm x (横) 13.0 cm x (高) 1.80 cm
重さ136 g (電池なし)
184 g (電池あり)
電池寿命?

メインで利用しないのは単に MacBook を利用している限り、とりあえず Trackpad は常に利用できるから。

Apple Magic Trackpad 2

後継の Magic Trackpad 2 は利用したことがありませんが、Force Touch 対応・充電池内臓でより使い勝手が増しているかもしれません。

無線形式Bluetooth 4.0
大きさ(縦) 11.49 cm x (横) 16.0 cm x (高) 1.06 cm
重さ231 g
電池寿命?

MacBook Pro 13 (Early 2011) のトラックパッドは Force Touch に対応していないので、Magic Trackpad 2 が利用できると嬉しいのですが、接続には Bluetooth 4.0 が必要で、私の所有している MacBook Pro 13 (Early 2011) では、そのままでは利用できません。

Microsoft Sculpt Touch Mouse (日本語サイト)

[写真] Sculpt Touch Mouse

Logitech V470 マウスが挙動不審だった際に、代替候補として購入。

特徴的なのはホイール部分のインタフェースで、ここが縦長のタッチセンサーになっています。クリックすると、センターボタンとして、なぞるとホイールとして利用できます (縦方向・横方向) 。

なぞった時に振動によるフィードバックがあるのも特徴。マウス側で勝手にやっているため、マウスの電源を入れてなぞれば フィードバックを感じることができます。

無線形式Bluetooth
トラッキングBlueTrack
大きさ(縦) 9.55 cm x (横) 6.5 cm x (高) 3.5 cm
重さ62 g (電池なし)
117 g (電池あり)
電池寿命9 ヶ月

どのレビューを見ても触れてありますが、やはり一番の難点はタッチセンサーの操作性。素早くなぞった時にホイールがしばらく回り続けるような慣性動作をサポートしたりしていますが、感度の調整不足なのか全体的に反応が微妙な感じ。

ホイール部のタッチセンサーが Magic Mouse や Trackpad 並の感度だったら、すごく良くなりそうなのに、この点が至極残念 (ソフトウェアで感度を変更できるようですが、Mac には対応していない模様)。

ホイールを使わず 3 ボタンマウスとしてなら、普通に使えるので、サブマウスとして時折使用する感じになっています。

Logitech M555b (日本語サイト)

[写真] M555b

挙動不審になってしまった Logitech V470 マウスの代替として購入。

繭型の V470 と比べて、ややのっぺりした感じの形状になっています。前述の Microsoft Sculpt Touch Mouse とは異なり、物理的なマウスホイールがあるマウスですが、二つのモードを切り替えることができるようになっているのが特徴的です。

慣性動作モードでは回した時のクリック感がなくなり、勢いよく回すことができます。長い文書を一気にスクロールしたい時などに有効。通常動作モードでは回した時に、クリック感があり、回した分だけホイール動作させることができます。

ホイール自体を押すとホイール動作モードの切り替えることができます。動作モードの切り替えにホイールボタンが使われるので、センターボタンがホイール直下に分かれて実装されています。

無線形式Bluetooth
トラッキングレーザー
大きさ(縦) 9.9 cm x (横) 5.8 cm x (高) 3.4 cm
重さ69 g (電池なし)
120 g (電池あり)
電池寿命2.5 ヶ月

ホイールがセンターボタンとして利用できないのには少し慣れが必要かもしれません。私はすぐに慣れました。ホイールの慣性動作はなかなか気持ちよいです。

慣性動作をサポートしている影響なのか、電池寿命が短いのが気になります。案外すぐに電池を交換しなくちゃいけない感じ。

しばらくメインのマウスとして利用していましたが、若干挙動不審気味なため、現在は後継機種の M557 を使っています。

Microsoft Designer Bluetooth Mouse (日本語サイト)

[写真] Designer Bluetooth Mouse

Logitech M555b/M557 をメインのマウスとして利用するようにしましたが、自宅と会社とそれぞれにマウスを置いておきたいと思って見つけたのが Microsoft Designer Bluetooth Mouse です。

とてもシンプルなデザインで、表面はつや消し処理されいるのか、光沢がありません。ベタベタ指紋がついたりしないし、触り心地がとても良いです。

ホイールは細いですが、金属製で剛性はしっかり。ホイールのチルト (横方向) には対応していません。電池用の蓋には爪などなく、磁石で付く仕様になっています。

ボタンが若干の静音設計になっているようで、しっかりしたクリック音はありますが、他のマウスと比べると低音かつ小音です。

無線形式Bluetooth 4.0
トラッキングBlueTrack
大きさ(縦) 10.7 cm x (横) 6.01 cm x (高) 2.6 cm
重さ57 g (電池なし)
80 g (電池あり)
電池寿命6 ヶ月

使い勝手は (良い意味で) とても普通。個人的には高さがあともう少しあると嬉しいかなとは思いますが、使用感には特に影響していないと思います。

利用するには Bluetooth 4.0 が必要なため、MacBook Pro 13 (Early 2011) では利用できないのが残念。そのため、MacBook Pro 13 用のメインマウスとしては利用できません。

Logitech M557 (日本語サイト)

[写真] M557

前述の M555b の後継機種が M557 です。ホイールの慣性動作がなくなった代わりに、ホイールがセンターボタンとして利用でき、また電池寿命が 12 ヶ月と大幅に伸びたのが特徴です。

おそらくホイール機構の単純化の影響でしょう、M555b と比べて本体重量もおよそ 10 g 程度軽くなっています (持ち比べると、マウス前方が軽くなっているのが分かります) 。

無線形式Bluetooth
トラッキングレーザー
大きさ(縦) 9.9 cm x (横) 5.8 cm x (高) 3.4 cm
重さ60 g (電池なし)
112 g (電池あり)
電池寿命12 ヶ月

形状・機能は M555b をそのまま踏襲していて、ホイールの慣性動作が利用できないという以外の点では使い勝手は M555b と同等。電池寿命が大幅に伸びたのは大きいです。交換すれば一年程度はもつので安心感があります。

Bluetooth 4.0 が必要ということもなく、MacBook Pro 13 (Early 2011) でも利用できるので、現在メインマウスとして利用しています。

Logitech MX Anywhere 2 (日本語サイト)

[写真] MX Anywhere 2

MX Anywhere 2 は Logitech の高級マウスの一つです。モバイル用と謳っていて、同じく高級マウスに分類される MX Master と比べると小ぶりで機能も抑えられています。

仕様を見ると、ほんの少しだけ M557 よりも大きいみたいですが、丸みを帯びた形状もあって、M557 よりも若干小ぶりに感じます。電池寿命は 2 ヶ月と M555b よりも短いんですが、充電池内臓で USB ケーブルを使って充電しながらでも利用できるので、個人的にはほとんど気になりません。

さすがに上位機種らしく、M555b 同様のホイールの慣性動作もサポートしていますし、切り替えボタンで一々ペアリングしなくてもサッと接続先マシンを切り替えることができる機能もあります (3 機種まで登録可能) 。

Bluetooth 4.0 が必要ですが、Logitech の Unifying 接続にも対応しているので、USB ポートをひとつ使ってしまう覚悟があれば、とりあえず MacBook Pro 13 (Early 2011) でも利用できます。

無線形式Bluetooth 4.0 / Unifying
トラッキングレーザー
大きさ(縦) 10.03 cm x (横) 6.16 cm x (高) 3.43 cm
重さ106 g
電池寿命2 ヶ月

Microsoft Designer Bluetooth Mouse のようなつや消しボディで触り心地が良く、加えて厚みが適度にあり、丸みを帯びた形状で M555b/M557 よりも手にフィットする感じで、さすが上位機種という使い勝手です。

MacBook Pro 13 (Early 2011) には Bluetooth で接続できないので、MacBook Pro 15 (Mid 2015) 用のメインマウスとして利用しています。

(おまけ) Microsoft Wireless Mouse 1000 (日本語サイト)

[写真] Wireless Mouse 1000

ワイヤレスマウスですが、USB レシーバを使うタイプですので、私のメインマウスには利用していません。ただ、USB 接続できるマウスを手元に置いておくと結構便利で、案外重宝しています。

Microsoft Wireless Mouse 1000 は Wireless Desktop 850 というキーボード・マウスのセット製品の一部です。単体で売っているのかどうかは分かりません。

無線形式2.4 GHz 帯ワイヤレス (USB レシーバ)
トラッキング光学式
大きさ(縦) 11.1 cm x (横) 5.6 cm x (高) 3.7 cm
重さ120 g (電池あり)
電池寿命8 ヶ月

無難なデザインで、やや重たい印象はありますが、使い勝手はいたって普通。可もなく不可もなくと言ったところ。

はてなブックマーク - ここ三、四年で利用している (利用した) ワイヤレスマウスの個人的まとめ

スポンサーリンク

Evernote 5.7 Mac で新しくなったプレゼンテーションモード

Evernote Mac 版 ver 5.7 が先日リリースされました。

[画像]Evernote 5.7 (Mac) が 10 月末にリリースされました。

このバージョンでは、Evernote Mac 版 ver 5.3 より搭載されたプレゼンテーションモードがバージョンアップされています。

プレゼンテーションモードはプレミアム (あるいはビジネス) 会員向けサービスですが、フリー会員でも 30 日間、一切の機能制限なく試用することができます。

[画像]新しいプレゼンテーションモードではレイアウト画面が追加されました。

レイアウトの編集

これまでのプレゼンテーションモードには、ノートに挿入された水平線を「改ページ」のように扱うという機能がありました。

新しいプレゼンテーションモードでは、水平線はそのまま水平線として扱うようになりました。改ページのような「区切り線」は新しく実装されたレイアウト画面で追加・編集できるようになります。

プレゼンテーションスクリーン右上にあるボタンが「レイアウト」ボタンです。

レイアウトを開くと、プレゼンテーションの縮小版が表示されて、表示したい箇所にさっとジャンプすることができます。

レイアウト画面右側に青いドットが表示されているのが分かるでしょうか。これは区切り線が挿入できるポイントを示しています。

マウスカーソルを持っていくと、どの位置に区切り線が挿入されるのか表示されます。そのままクリックすれば、区切り線が挿入されて、プレゼンテーションがその場で更新されます。

[画像]区切り線の追加は「+」ボタンで、追加した区切り線は「−」ボタンで行えます。

すでにある区切り線の横には「-」ボタンが表示されていて、それを押すとその区切り線を削除できます。区切り線はマウスでドラッグすることができて、区切り線の位置を変えたり、前後の区切り線と合わせたりすることでレイアウト調整ができます。

テーブル表示のサポート

Evernote Mac 版 ver 5.6 でエディタの機能が大きく改善されました。テーブルがより簡単に編集できるようになり、イメージのサイズも簡単に微調整できるようになりました。

これまでのプレゼンテーションモードでは、テーブル表示が崩れてしまったりすることがありましたが、大幅に改善さています。

[画像]テーブルの表示が大幅に改善されています。

イメージ表示のブラッシュアップ

これまでノートに貼り付けられたイメージは、プレゼンテーションモードでは画面中央に左右マージンをとって表示するような形で表示されていましたが、新しいプレゼンテーションモードでは、可能な限り大きく表示するようになりました。

特に縦長のイメージは、以前のプレゼンテーションモードでは常に画面に収まるように縮小されて表示されていました。新しいプレゼンテーションモードでは、この動作が変更されて、横幅が十分にある縦長のイメージに対しては、画面をはみ出して表示するようになっています。

[画像]縦長イメージも端から端まで使って表示するようになっています。

ウェブサイトのスクリーンショットなどで、スクロールする画面をくっつけたような縦長のスクリーンショットを見かけることがあると思いますが、そのようなスクリーンショットはとても自然に表示されることになります。

画面をはみ出してしまった縦長のイメージは、クリックすると縮小表示に切り替えることができますし、エディタ上で画像のサイズを変更すると、プレゼンテーションモードでもそれをそのまま利用するので、十分に小さくすれば、画面をはみ出さないように設定することもできます。

イメージ・テーブルの見出しと説明文

区切り線を調節することで、イメージやテーブル前後の文節を見出しや説明文として設定できるようになっています。

テキストでイメージ (テーブル) を挟み込むような形になるように区切り線を追加すると、イメージ (テーブル) 上部のテキストは見出しに、イメージ (テーブル) 下部のテキストは説明文として設定されて、それぞれ見た目が変わります。

[画像]区切り線を調整することで、イメージやテーブルにキャプションをつけることができるようになりました。

その他の改善点

外観のアップデート

タイトル表示やテキストの表示フォントがデザインし直されています。

[画像]新しくなったプレゼンテーションのデザイン

残念ながら、日本語での表示は以前とあまり大きく変わらないのですが、左右のマージンや行間なども微調整されていて、以前よりもさらにスッキリとした見栄えになっている感じがします。

表示フォントのサイズ変更

以前のプレゼンテーションモードでは、表示フォントサイズはほぼ固定でした。

新しいプレゼンテーションモードでは、表示フォントサイズを三段階で切り替えることができるようになりました。

スペースキー動作の改善

以前のプレゼンテーションモードでもスペースキーで下に移動、シフト + スペースキーで上に移動という動作になっていました。

[画像]スペースキーによる画面移動

以前のプレゼンテーションモードでも、区切りや貼り付けられたイメージを認識して、それがうまく表示されるように移動するという動作になっていましたが、新しいプレゼンテーションモードでは、その動作の精度が改善されています。

はてなブックマーク - Evernote 5.7 Mac で新しくなったプレゼンテーションモード

スポンサーリンク

Tinted image for UIImage

[画像]画面に表示するイメージ画像に色付けしたい……。

iOS のアプリケーションでハイライト状態などを示すため、生成した画像イメージに対して色付けしたいときがあります。

UIView には tintColor というプロパティがあって、色付けが簡単にできそうなのですが、イメージを表示する UIImageViewtintColor を設定しても何も変わりません。

そこで以下のようなヘルパークラスを用意して利用しています。

@interface SBLImageHelper
/**
 *  Generates an image which is tinted with a given color.
 *  @param image - an image to be tinted
 *  @param color - tint color
 *  @return an instance of UIImage
 */
+ (UIImage *)tintedImageFromImage:(UIImage *)image
                        withColor:(UIColor *)color;
@end


@implementation SBLImageHelper

+ (UIImage *)tintedImageFromImage:(UIImage *)image
                        withColor:(UIColor *)color
{
  UIImage *output = nil;
  CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);

  if (UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(image.size,
                                           NO,
                                           image.scale);
  }
  else
  {
    UIGraphicsBeginImageContext(image.size);
  }

  CGContextRef context = UIGraphicsGetCurrentContext();

  // -- flipping geometry
  CGContextTranslateCTM(context, 0, image.size.height);
  CGContextScaleCTM(context, 1.0, -1.0);

  // -- setting up blend mode
  CGContextSetBlendMode(context, kCGBlendModeNormal);

  // -- first drawing the image
  CGContextDrawImage(context, rect, image.CGImage);

  // -- then setting up mask and fill the color
  CGContextClipToMask(context, rect, image.CGImage);
  CGContextSetFillColorWithColor(context, color.CGColor);
  CGContextFillRect(context, rect);

  output = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return output;
}

@end

次のように使います。

UIColor *tintColor = [[UIColor redColor] colorWithAlphaComponent:0.5];
UIImage *originalImage = [UIImage imageNamed:@"sample"];
UIImage *tintedImage = [SBLImageHelper tintedImageFromImage:originalImage
                                                  withColor:tintColor];

Objective-C にはカテゴリーという既存のクラスを拡張するための仕組みがありますが、すでにあるメソッドと同じ名前のメソッドを追加すると、どっちのメソッドが利用されるか分からなくなってしまうという強烈な副作用があります。

ですので、個人的にはあまりオススメしませんが、UIImage のカテゴリーとして拡張するバージョンだと以下のようになるでしょうか。

@interface UIImage (SBLImageHelper)
/**
 *  Generates an image which is tinted with a given color.
 *  @param color - tint color
 *  @return an instance of UIImage
 */
- (UIImage *)imageWithTintColor:(UIColor *)color;

@end


@implementation UIImage (SBLImageHelper)

- (UIImage *)imageWithTintColor:(UIColor *)color
{
  UIImage *output = nil;
  CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

  if (UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(self.size,
                                           NO,
                                           self.scale);
  }
  else
  {
    UIGraphicsBeginImageContext(self.size);
  }

  CGContextRef context = UIGraphicsGetCurrentContext();

  // -- flipping geometry
  CGContextTranslateCTM(context, 0, self.size.height);
  CGContextScaleCTM(context, 1.0, -1.0);

  // -- setting up blend mode
  CGContextSetBlendMode(context, kCGBlendModeNormal);

  // -- first drawing the image
  CGContextDrawImage(context, rect, self.CGImage);

  // -- then setting up mask and fill the color
  CGContextClipToMask(context, rect, self.CGImage);
  CGContextSetFillColorWithColor(context, color.CGColor);
  CGContextFillRect(context, rect);

  output = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return output;
}

@end

この記事は qiita.com の内容を再掲載したものです。

はてなブックマーク - Tinted image for UIImage

スポンサーリンク

Re: 今日のiPhoneホーム画面

salchuさんの「今日のiPhoneホーム画面」に触発されて、私もホームスクリーン晒し。

この間、日本でお会いした時には iPhone 持っていなかったので、お見せできなかったですものね。多分、iOS6 でのホーム画面はこれが最終形になるかと。五つの画面をひとまとめにしてしまったので、見づらくてごめんなさい。

[画像] iOS6 でのホーム画面

スクリーン 1
Apple 標準アプリのみ。"Podcast" は、半標準ということで。
スクリーン 2
ソーシャル系・日常で利用するアプリ。左に赤系・右に青系を置いてます。
スクリーン 3
Apple, Google, Evernote を順に並べて、自作アプリもここに。
スクリーン 4
辞書系・読書系のアプリ。
スクリーン 5
銀行関連・乗り換え案内関連。あといくつか普段あまり利用しないやつも。

傾向として……

  • フォルダはあまり使わない。
  • 同系色はまとめたい。
  • よく利用するアプリほど下に配置したい。

といった感じでしょうか。

地図は標準 Map と Google Map を半々で利用する感じ。これまでのところ、標準の Map で使いづらいとか困ったとかあまり感じたことがないので、特に Google Map じゃないとダメという感じではないです。

二ページ目は左側の赤系・右側に青系と決めているんですけど、そのせいであまり使わない mixi とか Foursquare が入ってしまっているのはご愛嬌。Gmail, ATOK Pad, Facebook, Dropbox は、ビューワとしてほぼ毎日使ってます。

iOS7 になると、おそらくまた構成が変わると思うので、この状態があと何日もつかは不明ですけれども。

あ、ちなみに iOS で最も頻繁に使っていると思われるアプリは Settings (設定) です。カメラはもっぱらロックスクリーンからアクセスするのでどこに置いても変わらないという。

はてなブックマーク - Re: 今日のiPhoneホーム画面

スポンサーリンク

mi 3.0.0b1 - mi ver 3 のファーストベータ

多機能エディタ mi の新バージョン ver 3 の最初のベータ版が公開されました

ver 3 になって Cocoa フレームワークを利用したアプリケーションとして作り直されています。

そのため Maximizer のような Cocoa アプリケーションにしか効かない SIMBL プラグインも利用できるようになっています。フルスクリーンで mi が利用できるように。

UI のアピアランスが大きく変更されました。Cocoa フレームワークを利用したこと影響も大きいのでしょう、全体的にモダンな UI に変わっています。

[画像] mi ver 3 - インタフェースが刷新されました。

アウトラインは「見出しリスト」という形で従来からサポートされていましたが、それが強化されて、セクション毎に折畳みができるようになっています。

モダンなエディタらしく (?) 選択されたテキストなどに対して、同一ファイル内に存在する同じワードが全てハイライト表示されたりします。

モードや設定などは ver 2 から引き継がれますが、設定ファイルは別に保存されているので併用も可能です。

私の環境ではモード毎に設定されているツールに割り当てていたキーバインドの一部が引き継がれませんでしたが (一部、新規追加されたデフォルトのキーバインドと被っていたせいかもしれません)、概ね以前のままの状態でそのまま利用できる印象です。

英語リソースの対応はまだのようで、英語環境で立ち上げると英語と日本語が交じったインタフェースになってしまうのはご愛嬌。…… ver 2 から引き継がれたメニューやインタフェースは英語化されていて、新規に追加された分が英語化されていないという感じの状態になっています。

アプリケーション設定・モード設定が大幅に見直されてとても分かりやすくなっています。

[画像] mi ver 3 - 設定ウィンドウが大幅に刷新されています。

特にカラー設定は「カラースキーム」という csv ファイルで定義されるようになり、インポート・エクスポートが簡単にできて管理しやすくなっています。インタフェースも分かりやすい。

ver 2 では subversion などバージョン管理システムで管理されたファイルに対して差分表示を行う機能がありましたが、ver 3 では、差分表示機能そのものが大幅に強化されて、自動保存による履歴差分や他のファイルの差分表示などもサポートするようになっています。

[画像] mi ver 3 - 新規に追加された差分表示機能。

私の環境では Retina ディスプレイでの表示を確認することはできませんが、アプリケーション内のリソースを見ると一部アイコンなどはベクター画像が利用されたりしていて、Retina 表示にも対応しているようです。

アプリケーションアイコンも前掲の通り刷新されました。「ミミカキ」がなくなっていますが、最大サイズ (1024 x 1024) で見るとハイライトペンのところに、さりげなく「MI3」の文字が……。細かい。

[画像] mi ver 3 - アプリケーションアイコンに隠された (?) MI3 の文字。

アイコンでキャプチャされている書類は、なんらかのソースコードに見えます。なんだろう……。コードスタイルから見ると c++ っぽい感じのコード。

まだざっとしか利用していませんが、安定して動作しています。パフォーマンスに関しては今のところ従来と同等な印象ですが、大きなファイルを開いたり、マルチファイル検索などの比較的重めな処理は行っていないので、これから確認という感じです。

ver 3 ではフリー版・有料版・AppStore 版とリリースされる予定ですが、今回ざっと紹介した機能のどこまでフリー版のものか、有料版のものかなどの詳細はまだ分かりません。ともあれ今後の展開にとっても楽しみです。

はてなブックマーク - mi 3.0.0b1 - mi ver 3 のファーストベータ

スポンサーリンク

汎用コードを複数の iOS アプリケーション開発で共有利用する手法

いくつかの iOS アプリケーションを開発していると、自然と共有できるコードが増えてきます。

そうした共有可能な汎用コードを複数のアプリケーションのプロジェクトで利用する方法はいくつか考えられます。

アプリケーションのプロジェクトに組み込む

別リポジトリで管理している汎用コードを svn externals や git submodule などを使ってリンクして、それをそのままアプリケーションのプロジェクトに組み込みます。

svn や git などバージョン管理ソフトウェアの機能だけを利用しているので、仕組み自体はとてもシンプルになります。

構成はシンプルになりますが、その分運用でカバーしなくてはいけない点があります。

  • 汎用コード部分のビルドがアプリケーションのプロジェクトに依存するので、汎用コード部分の独立性を保つのに注意が必要。

  • 汎用コード部分でファイルの追加・削除があった場合、それを参照している全てのアプリケーションプロジェクトを逐次変更しなくてはならない。

  • 汎用コードを利用する新規アプリケーションプロジェクトを作成して、リンクしたリポジトリを取り込む際、ターゲットに含めるファイルとそうでないファイルの切り分けが必要。

総じて独立性が乏しい分、手順が増える傾向があります。

静的ライブラリとして生成する

汎用コード部分を静的ライブラリとして作成して、アプリケーションのプロジェクトにライブラリとして登録します。

静的ライブラリを作成するプロジェクトファイルがアプリケーションのプロジェクトとは独立した形で作成されるので、アプリケーションのプロジェクトに依存することなく、ビルド・ユニットテストを行うことができます。

Xcode は外部プロジェクトもプロジェクトに組み込めるので、アプリケーションをビルドする際に都度静的ライブラリを生成するような形で運用することも可能です。

Xcode の基本機能だけで完結しますし、手順もそれほど難しくはないのですが、イメージや xib などのバイナリリソースが静的ライブラリには、そのまま組み込めないという制約があります。

イメージなどのバイナリリソースは静的ライブラリとは別にアプリケーションのプロジェクトに組み込む必要があります。

その場合、汎用コード部分で利用されるリソースファイルの追加・削除の手間は前述の組み込み型と同等になります。

フレームワークとして生成する

静的ライブラリではリソースは組み込めないのですが、フレームワークという仕組みを利用するとリソースも込みでライブラリを生成することができます。

UIKit などはフレームワークの形で配布されて、ほぼ全てのネイティブ iOS アプリケーションで利用されています。

汎用コード・リソースの共有化という点では最適な方法なのですが、Xcode の標準な方法ではサポートされないという欠点があります。

Mac OS X 向けアプリケーションに対してはフレームワーク生成がサポートされていますが、iOS プラットフォームではサポートされていません。

iOS ユニバーサルフレームワークなどを利用すると iOS プラットフォーム向けフレームワークを作成することができます。

github での説明を見ても分かる通り、現状ではややハック的な運用にならざる得ないようです。Fake Framework という仕組みではバンドルを利用していたりするみたい。

静的ライブラリをリソース込みで生成する

拙作 SBPullToRefreshHeaderView のようにリソース込みな汎用コードがある場合、リソースがあるのでやはりフレームワークを使う方法になると思います。

ハック的な運用を避けて、Xcode 標準な機能だけでなんとかならないか、と探していたところ、Compiling Image Resources into a Static Library という記事を見つけました。

静的ライブラリにはバイナリリソースは組み込ませんが、バイナリを C コードの形でダンプしてコンパイルしてしまえば、データとして組み込むことが可能になります。

  1. イメージなどのバイナリを xxd -i コマンドを使って C コードに変換
  2. コード化されたデータを UIImage など Objective-C クラスに変換するローダーを生成
  3. リソースはローダーを介して読み込む

Compiling Image Resources into a Static Library では、イメージだけ処理していますが、同様に nib ファイルも処理できます。具体的な手順については後日改めて。

はてなブックマーク - 汎用コードを複数の iOS アプリケーション開発で共有利用する手法

スポンサーリンク

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 デバイス一覧表

スポンサーリンク

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 利用時のインスタンス破棄タイミングについて

スポンサーリンク

1/9