2010-05-27 2 views
0

я создал вспомогательный класс UIButton:подклассы UIButton, но не может получить доступ к моему свойству

// 
// DetailButton.h 
#import <Foundation/Foundation.h> 
#import <MapKit/MapKit.h> 

@interface MyDetailButton : UIButton { 
    NSObject *annotation; 
} 

@property (nonatomic, retain) NSObject *annotation; 


@end 

// 
// DetailButton.m 
// 


#import "MyDetailButton.h" 


@implementation MyDetailButton 


@synthesize annotation; 

@end 

я понял, что я могу затем создать этот объект и установить объект аннотаций, выполнив следующие действия:

MyDetailButton* rightButton = [MyDetailButton buttonWithType:UIButtonTypeDetailDisclosure]; 
rightButton.annotation = localAnnotation; 

localAnnation - это NSObject, но это действительно MKAnnotation. Я не могу понять, почему это не работает, но во время выполнения я получаю эту ошибку:

2010-05-27 10:37:29.214 DonorMapProto1[5241:207] *** -[UIButton annotation]: unrecognized selector sent to instance 0x445a190 
2010-05-27 10:37:29.215 DonorMapProto1[5241:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIButton annotation]: unrecognized selector sent to instance 0x445a190' 

'

Я не могу понять, почему это даже не смотря на UIButton, потому что я подклассы, что так оно должен посмотреть класс MyDetailButton, чтобы установить это свойство аннотации. Я пропустил что-то действительно очевидное. Такое ощущение, что это :)

Заранее спасибо за любую помощь вы можете предоставить

Росс

+0

подклассов 'UIButton' является боль (так как' UIButton' класс кластера). Есть ли другой способ сделать это? –

ответ

0

Просто делает подкласс не достаточно; подкласс не заменяет свой суперкласс. Точно так же не все UIControls, не все UIViews, не все UIResponders, а не все NSObjects имеют поведение UIButton, не все UIButtons имеют поведение вашего пользовательского подкласса.

Что вам нужно, это экземпляр вашего подкласса. У вас есть экземпляр UIButton.

Решение заключается в том, чтобы сделать экземпляр экземпляром вашего подкласса. Если вы создали кнопку в Interface Builder, выберите кнопку и нажмите ⌘6, а затем измените свой собственный класс экземпляра. Если вы создаете кнопку в коде, отправьте сообщение alloc в свой собственный подкласс, а не непосредственно в UIButton.

+0

Спасибо за быстрый ответ. Я думал, что сделал экземпляр своего подкласса, выполнив: MyDetailButton * rightButton = [MyDetailButton buttonWithType: UIButtonTypeDetailDisclosure]; С тех пор я нашел способ обойти это с помощью метода -mapView: annotationView: calloutAcessoryControlTapped, но мне все равно хотелось бы знать, что я сделал не так. Есть ли еще код, который я могу предоставить, который поможет? –

+0

Это похоже на то, что он создает подкласс, но если вы получаете это исключение во время выполнения, то что-то отправляет сообщение «аннотации» на простой старый UIButton. Установите точку останова на 'objc_exception_throw' в отладчике, затем запустите приложение под отладчиком, и вы сможете посмотреть вокруг и посмотреть, где проблема. Если это код, который вы показали, то возможно, что этот метод просто возвращает UIButton безоговорочно (по крайней мере, для этого типа кнопки), вместо того, чтобы использовать класс, на который вы отправили сообщение 'buttonWithType:'. –

1

Это исключение связано с тем, что фактическая кнопка, с которой вы пытаетесь получить аннотацию, равна не класса MyDetailButton, это UIButton. Убедитесь, что вы задали класс в IB для этой конкретной кнопки. Выберите кнопку в IB и нажмите ⌘4, чтобы увидеть ее личность, измените идентификатор класса на MyDetailButton.

14

UIButton класс кластера, который предполагает, что реализация Яблока buttonWithType:, вероятно, выглядит примерно так:

+(id)buttonWithType:(UIButtonType)t { 
    switch (t) { 
    case UIButtonTypeDetailDisclosure: 
     return [[[PrivateDetailDisclosureButtonClass alloc] init] autorelease]; 
    case ... 
    } 
} 

Так что, когда вы звоните [MyDetailButton buttonWithType:UIButtonTypeDetailDisclosure]; вы не получите экземпляр MyDetailButton, вы получите экземпляр PrivateDetailDisclosureButtonClass (или то, что на самом деле называет его Apple).

Заметим, однако, что вы можете получить buttonWithType создать экземпляр подкласса, если вы называете его с UIButtonTypeCustom (по крайней мере, в тренажере работает v3.0):

// LGButton is a straightforward subclass of UIButton 
LGButton *testBtn = [LGButton buttonWithType:UIButtonTypeCustom]; 
LGButton *testBtn2 = [LGButton buttonWithType:UIButtonTypeDetailDisclosure]; 
NSLog(@"testBtn: %@, testBtn2: %@", [testBtn class], [testBtn2 class]); 
// Output: testBtn: LGButton, testBtn2: UIButton 
2

Я сделал ту же попытку, как оригинальный постер, но кажется, что подклассификация UIButton для выполнения чего-то подобного сложна.

Что я сделал, это взломать - но теперь для меня работает, добавляет UITextField как подпункт UIButton. UITextField не имеет фрейма и скрыт, но я могу свободно хранить текстовые строки в текстовом свойстве текстового поля. Это то, что я хотел сделать ...

UITextField* tf = [[UITextField alloc] init]; 
tf.text = @"the text that I wanna store"; 
tf.hidden = YES; 
tf.tag = TAGOFBUTTONSUBTEXTFIELD; 
[previouslyCreatedButton addSubview:tf]; 
[tf release]; 

Я определил TAGOFBUTTONSUBTEXTFIELD как 99 где-то. Глобальный. Это некрасиво, но ...

Тогда позже, чтобы получить, что использование текстовых строк что-то вроде этого:

+(NSString*)getStoredStringFromButton:(UIButton*)button { 
    UITextField* tf = (UITextField*)[button viewWithTag:TAGOFBUTTONSUBTEXTFIELD]; 
    return tf.text; 
} 

Так что это предполагает, что никто не пытается добавить подвид с тегом 99 к кнопке.

Лол :-)

Смежные вопросы