Подкласс UIButton отображается неправильно - PullRequest
0 голосов
/ 08 июля 2011

У меня есть кнопка, созданная с помощью файла NIB.Я получил класс из UIButton, заменил имя класса в файле NIB.

Теперь моя кнопка отображается без фона.Текст есть, шрифт и цвет текста правильные, и он реагирует на нажатия, как и ожидалось, но это как если бы фон был прозрачным.В NIB это не прозрачно - я не изменил ни одно из свойств, кроме имени класса.

Подкласс тривиален - он ничего не переопределяет (пока).Пожалуйста, что я делаю не так?

Причина, по которой мне нужен подкласс UIButton, заключается в том, что я хочу, при определенных обстоятельствах, иметь возможность перетаскивать текст с кнопки в другое место.Если есть альтернативный способ обработки перетаскивания в представлении UIKit, я готов услышать.

Ответы [ 2 ]

0 голосов
/ 12 июля 2011

Честно говоря, не уверен, что не так с подклассом, но сеть (включая 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).

0 голосов
/ 08 июля 2011

Проверьте состояния кнопки в вашем файле NIB.Возможно, вы смотрите на «активное» состояние или что-то еще, а не на более распространенное UICONTROLSTATENORMAL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...