цель C: кнопки, созданные из подкласса класса UIButton, не работают - PullRequest
14 голосов
/ 22 июня 2011

Я создаю подкласс UIButton, чтобы создавать свои собственные настраиваемые кнопки.Мой код выглядит следующим образом:

//interface file (subclass of uIButton
@interface UICustomButton : UIButton 
{
    Answer *answer;
    NSString *btnType;
}

@property (nonatomic, retain) Answer *answer;
@property (nonatomic, assign) NSString *btnType;

- (id)initWithAnswer:(Answer *)ans andButtonType:(NSString *)type andFrame:(CGRect)frame; 
- (void)buttonPressed;

@end


//Implementation file (.m)
@implementation UICustomButton
@synthesize answer,btnType;

- (id)initWithAnswer:(Answer *)ans andButtonType:(NSString *)type andFrame:(CGRect)frame; 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        self = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        self.backgroundColor = [UIColor colorWithHexString:@"#E2E4E7"];

    }

    [self addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlStateNormal];

    self.answer = ans;
    self.btnType = type;

    return self;
}

Я столкнулся с некоторыми проблемами при получении вышеуказанного кода для работы.У меня 2 проблемы

1) Кнопки не реагируют на метод селектора «buttonPressed»

2) У меня возникает ошибка времени выполнения для строк «self.answer = ans» иself.btnType = type 'Трассировка стека следующим образом:

-[UIButton setAnswer:]: unrecognized selector sent to instance 0x614ebc0
2011-06-23 00:55:27.038 onethingaday[97355:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton setAnswer:]: unrecognized selector sent to instance 0x614ebc0'

Что я здесь не так делаю?

Ответы [ 5 ]

30 голосов
/ 22 июня 2011

Это происходит потому, что вы создаете объект типа UIButton, а не тип UICustomButton внутри метода init, когда выполняете

self = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];

Попробуйте заменить метод init на

- (id)initWithAnswer:(Answer *)ans andButtonType:(NSString *)type andFrame:(CGRect)frame; 
{
    self = [self initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
    if (self) 
    {
        self.backgroundColor = [UIColor colorWithHexString:@"#E2E4E7"];

        [self addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];

        self.answer = ans;
        self.btnType = type;
    }

    return self;
}

Это приведет к тому, что self будет объектом типа UICustomButton.

Кроме того, вы используете неверный тип для параметра UIControlState, когда добавляете цель к своей кнопке, используя метод addTarget:action:forControlEvents:

Вы должны использовать значение среди приведенных ниже:

UIControlEventTouchDown
UIControlEventTouchDownRepeat
UIControlEventTouchDragInside
UIControlEventTouchDragOutside
UIControlEventTouchDragEnter
UIControlEventTouchDragExit
UIControlEventTouchUpInside
UIControlEventTouchUpOutside
UIControlEventTouchCancel


EDIT: Замечания по подклассам UIButton

Многие ссылки в Интернете говорят, что вы НЕ должны делить класс UIButton на подклассы, но не только кто-то сказал, почему, но меня также очень раздражало то, что UIButton Class Reference ничего не говорит об этом в все.

Если вы берете UIWebView Class Reference , например, в нем прямо говорится, что вы не должны подкласс UIWebView

Примечания по подклассам Класс UIWebView не должно быть подклассом.

большая проблема с UIButton заключается в том, что он наследуется от UIControl, а хорошее и простое объяснение содержится в справочнике классов UIControl *

Примечания по подклассам Вы можете захотеть расширить подкласс UIControl для любого по двум причинам:

  • Для наблюдения или изменения отправки сообщения о действиях для целей отдельные события
  • Для предоставления пользовательских отслеживание поведения (например, для изменить внешний вид подсветки)

Итак, это означает, что вы CAN подкласс UIButton, но вы должны быть осторожны в том, что вы делаете. Просто создайте подкласс, чтобы изменить его поведение и , а не его внешний вид . Чтобы изменить внешний вид UIButton, вы должны использовать методы интерфейса, предусмотренные для этого, такие как:

setTitle: forState:
setBackgroundImage: forState:
setImage: forState:

Список литературы, которую стоит прочитать

Источник: мой пост здесь

10 голосов
/ 10 мая 2013

Не уверен, что это было в документах раньше, но в любом случае это текущие заметки по + (id)buttonWithType:(UIButtonType)buttonType ...

Мне кажется, что подклассы в порядке, если вы используете init вместоbuttonWithType.Тем не менее, я еще не попробовал сам.

Обсуждение Этот метод является удобным конструктором для создания объектов кнопок с определенными конфигурациями.Если вы подкласс UIButton, этот метод не возвращает экземпляр вашего подкласса.Если вы хотите создать экземпляр определенного подкласса, вы должны непосредственно выделить / инициализировать кнопку.

При создании пользовательской кнопки, то есть кнопки с типом UIButtonTypeCustom, для рамки кнопки устанавливается значение(0, 0, 0, 0) изначально.Прежде чем добавить кнопку в свой интерфейс, вы должны обновить фрейм до более подходящего значения.

0 голосов
/ 27 февраля 2015

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

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesBegan");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesEnded");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesCancelled");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesMoved");
}

Метод инициализации не требуется.

0 голосов
/ 28 августа 2014
//
//  BtnClass.m

#import "BtnClass.h"

@implementation BtnClass

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code


    }
    return self;
}

//added custum properities to button
-(id)initWithCoder:(NSCoder *)aDecoder
{
    NSLog(@"initWithCoder");
    self = [super initWithCoder: aDecoder];
    if (self) {
        // Initialization code

        _numberOfItems=[[UILabel alloc]initWithFrame:CGRectMake(40, 8, 160, 30)];
        _numberOfItems.textAlignment=NSTextAlignmentLeft;
        _numberOfItems.font = [UIFont boldSystemFontOfSize:18.0];
        _numberOfItems.textColor = [UIColor darkGrayColor];
        [self addSubview:_numberOfItems];
        _leftImage=[[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 25, 25)];
        [self addSubview:_leftImage];
        _rightImage=[[UIImageView alloc]initWithFrame:CGRectMake(280, 10, 15, 15)];
        [self addSubview:_rightImage];
        [self setImage:[UIImage imageNamed:@"list-bg2-1.png"] forState:UIControlStateNormal];
        [_rightImage setImage:[UIImage imageNamed:@"carat.png"]];
        self.backgroundColor=[UIColor blackColor];


        if(self.tag==1)
        {
            [_leftImage setImage:[UIImage imageNamed:@"notes-icon.png"]];

        }
        if(self.tag==2)
        {
            [_leftImage setImage:[UIImage imageNamed:@"photos-icon.png"]];

        }
        if(self.tag==3)
        {
            [_leftImage setImage:[UIImage imageNamed:@"videos-icon.png"]];

        }


    }
    return self;
}

//selected method of uibutton
-(void)setSelected:(BOOL)selected
{

    [super setSelected:selected];


    if(selected)
    {
        [self setImage:nil forState:UIControlStateNormal];
        _numberOfItems.textColor = [UIColor whiteColor];

        [_rightImage setImage:[UIImage imageNamed:@"carat-open.png"]];

        if(self.tag==1)
        {
            [_leftImage setImage:[UIImage imageNamed:@"white-notes-icon.png"]];
        }
        else if(self.tag==2)
        {

            [_leftImage setImage:[UIImage imageNamed:@"white-photo-icon.png"]];

        }
        else
        {
            [_leftImage setImage:[UIImage imageNamed:@"white-video-icon.png"]];

        }

    }
    else{

        _numberOfItems.textColor = [UIColor darkGrayColor];

        if(self.tag==1)
        {
            [_leftImage setImage:[UIImage imageNamed:@"notes-icon.png"]];

        }
        if(self.tag==2)
        {
            [_leftImage setImage:[UIImage imageNamed:@"photos-icon.png"]];

        }
        if(self.tag==3)
        {
            [_leftImage setImage:[UIImage imageNamed:@"videos-icon.png"]];

        }

        [self setImage:[UIImage imageNamed:@"list-bg2-1.png"] forState:UIControlStateNormal];

        [_rightImage setImage:[UIImage imageNamed:@"carat.png"]];

    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end
0 голосов
/ 22 июня 2011

Редактировать

Этот ответ длится уже несколько лет, и ситуация изменилась - поскольку в документах Apple теперь явно упоминается о подклассах и даются некоторые подсказки.

Итак, следующий ответможет быть неактуальным или неправильным для текущей разработки и может быть проигнорировано, если вас интересует текущее состояние.


UIButton означает , а не быть разделенным на подклассы.

Вам лучше создать категорию и определить заводской метод, который доставит нужную вам кнопку (с правильным вызовом buttonWithType:).initWithFrame: неверный способ инициализации кнопки в любом случае.

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