真的不知道有什麼不對的子類,但「網(包括SO)全是有關繼承UIButton的警世故事,怎麼你不應該。
所以我會用四種觸摸處理方法來調整方法。下面的函數取代了按鈕的設置方法與我的實現(從myButton的類所),同時節省了舊系統中的按鈕類根據不同的選擇:
//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]:@@");
}
}
,並呼籲它這樣:
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的。所以我的第一個天真的混合實現將取代UIControl中的方法而不是按鈕類。目前的實施方式並不以任何方式。此外,它不會假設按鈕的運行時類。可以是UIButton,可以是任何東西(並且在真正的iOS中,它是UIRoundedRectButton)。
不,背景和alpha設置爲所有狀態。 –