正に、サブクラスに何が問題なのかよくわからないが、 'Net(SOを含む)はUIButtonをサブクラス化するための注意書きでいっぱいだ。
ここでは、4つのタッチ処理方法に驚くような方法を取り上げます。
//Does NOT look at superclasses
static bool MethodInClass(Class c, SEL sel)
{
unsigned n,i ;
Method *m = class_copyMethodList(c, &n);
for(i=0;i<n;i++)
{
if(sel_isEqual(method_getName(m[i]), sel))
return true;
}
return false;
}
static void MountMethod(Class &buc, SEL SrcSel, SEL SaveSlotSel)
{
IMP OldImp = [buc instanceMethodForSelector:SrcSel];
IMP NewImp = [[MyButton class] instanceMethodForSelector:SrcSel];
if(OldImp && NewImp)
{
//Save the old implementation. Might conflict if the technique is used
//independently on many classes in the same hierarchy
Method SaveMe = class_getInstanceMethod(buc, SaveSlotSel);
if(SaveMe == NULL)
class_addMethod(buc, SaveSlotSel, OldImp, "[email protected]:@@");
else
method_setImplementation(SaveMe, OldImp);
//Note: the method's original implemenation might've been in the base class
if(MethodInClass(buc, SrcSel))
{
Method SrcMe = class_getInstanceMethod(buc, SrcSel);
if(SrcMe)
method_setImplementation(SrcMe, NewImp);
}
else //Add an override in the current class
class_addMethod(buc, SrcSel, NewImp, "[email protected]:@@");
}
}
そしてそれを呼び出す:
を別のセレクタの下で、システムのボタンクラスの古いものを節約しながら、以下の機能は、(MyButtonというクラスから撮影した)私の実装で、ボタンの提供方法を置き換えます
Class buc = [bu class];
MountMethod(buc, @selector(touchesBegan:withEvent:), @selector(MyButton_SavedTouchesBegan:withEvent:));
MountMethod(buc, @selector(touchesCancelled:withEvent:), @selector(MyButton_SavedTouchesCancelled:withEvent:));
MountMethod(buc, @selector(touchesEnded:withEvent:), @selector(MyButton_SavedTouchesEnded:withEvent:));
MountMethod(buc, @selector(touchesMoved:withEvent:), @selector(MyButton_SavedTouchesMoved:withEvent:));
これは、所望のものだけでなく、すべてのボタンに対して前記方法を実装するという欠点を有する。 MyButtonの実装では、この特定のボタンに対してドラッグドロップ機能を有効にするかどうかをさらに確認します。そのために、関連するオブジェクトを使用しました。
touchesXXXメソッドがUIControlクラスで実装されていて、UIButtonで実装されていない点が1つあります。だから私の最初の、素朴なスウィズリングの実装は、ボタンクラスの代わりにUIControlのメソッドを置き換えます。現在の実装はどちらの方法も想定していません。また、ランタイムクラスのボタンについては何も想定していません。 UIButton、何でもかまいません(実際のiOSではUIRoundedRectButtonです)。
いいえ、すべての状態に対して背景とアルファが設定されています。 –