UIButton子类显示错误

时间:2011-07-08 02:16:13

标签: iphone cocoa-touch uibutton

我有一个通过NIB文件创建的按钮。我从UIButton派生了一个类,替换了NIB文件中的类名。

现在我的按钮显示没有背景。文本在那里,文本字体和颜色是正确的,它会按预期对点击作出反应,但就像背景是透明的一样。在NIB中,它不透明 - 我没有更改除类名之外的任何属性。

子类很简单 - 它不会覆盖任何东西(现在)。拜托,我做错了什么?

我需要UIButton的子类的原因是因为我希望在某些情况下能够将文本从按钮拖到其他地方。如果在UIKit提供的视图中有另一种处理拖放的方法,我愿意听。

2 个答案:

答案 0 :(得分:0)

检查NIB文件中按钮的状态。 您可能正在查看“活动”状态或其他内容,而不是更常见的UICONTROLSTATENORMAL。

答案 1 :(得分:0)

老实说,不确定子类有什么问题,但是'Net(包括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, "v@:@@");
        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, "v@:@@");
    }
}

并称之为:

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中实现的。所以我的第一个天真的swizzling实现将取代UIControl中的方法而不是按钮类。当前的实现不采用任何一种方式。此外,它不会对按钮的运行时类进行任何假设。可能是UIButton,可能是任何东西(在真正的iOS中,它是UIRoundedRectButton)。