2013年1月8日火曜日

メニューにアイコンを - CXAImageSupport

これはいい。




使い方も簡単。UIMenuItemにイメージをセットするだけ。
UIMenuItem *cameraItem = [[UIMenuItem alloc] initWithTitle:nil action:@selector(cameraAction:)];
  [cameraItem cxa_setImage:[UIImage imageNamed:@"camera"] hidesShadow:YES forTitle:NSLocalizedString(@"Camera", nil)];


実現方法は面白くて、method swizzlingを使い本来テキストを描画するdrawTextInRectを書き換えて画像描画に対応させている。
Method origMethod = class_getInstanceMethod(self, @selector(drawTextInRect:));
  origDrawTextInRect = (void *)method_getImplementation(origMethod);
  if (!class_addMethod(self, @selector(drawTextInRect:), (IMP)newDrawTextInRect, method_getTypeEncoding(origMethod)))
    method_setImplementation(origMethod, (IMP)newDrawTextInRect);
   :

なおUIMenuItemのカテゴリとして実装してある為、画像や設定(影)をグローバル変数で持っている(NSMutableDictionary* titleImagePairs)。cxa_setImage:hidesShadow:forTitle: のタイトル文字列はこの辞書のキーとして使われている。その為、タイトル文字は表示されないが必須でかつ重複はできない(と思われる)。

コードは短くて無駄が無い。何よりもアイディアがいいと思った。

ライセンス:MIT




メモ)NSMutableDictionaryの初期化はこんな風にかけるのか。
+ (void)load
{
  static dispatch_once_t once;
  dispatch_once(&once, ^{
    titleImagePairs = [@{} mutableCopy];
    titleHidesShadowPairs = [@{} mutableCopy];
  });
}

関連)blocksベースのUIMenuItemビルダ。



0 件のコメント:

コメントを投稿