开发者

Subclassing UIButton but can't access my properties

I've created a sub class of 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

I figured that I can then create this object and set the annotation object by doing the following:

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

localAnnotation is an NSObject but it is really an MKAnnotation. I can't see why this doesn't work but at runtime I get this error:

 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'

'

I can't see why it's even looking at UIButton because I've subclassed that so it should be looking at the MyDetailButton class to set that annotation property. Have I mi开发者_JAVA技巧ssed something really obvious. It feels like it :)

Thanks in advance for any help you can provide

Ross


UIButton is a class cluster, which implies that Apple's implementation of buttonWithType: probably looks something like this:

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

So when you call [MyDetailButton buttonWithType:UIButtonTypeDetailDisclosure]; you don't get an instance of MyDetailButton, you get an instance of PrivateDetailDisclosureButtonClass (or whatever Apple actually calls it).

Note, however, that you can get buttonWithType to instantiate a subclass if you call it with UIButtonTypeCustom (At least in the simulator running 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


I made the same attempt as original poster but it seems that subclassing UIButton to do something like this is hard.

What I did, which is a hack - but works for me now, is add a UITextField as subview of the UIButton. The UITextField has no frame and is hidden, but I can freely store text strings in the textfield's text property. Which is what I wanted to do...

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

I defined TAGOFBUTTONSUBTEXTFIELD as 99 somewhere. Global. It's ugly but...

Then later, to get that text string use something like this:

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

So this assumes that no one else tries to add a subview with tag 99 to the button.

Lol :-)


That exception is because the actual button that you are trying to get the annotation from is not of class MyDetailButton, it is a UIButton. Verify that you set the class in IB for that particular button. Select the button in IB and press ⌘4 to see its identity, change the Class Identity to MyDetailButton.


Just making a subclass isn't enough; the subclass does not take the place of its superclass. The same way not all UIControls, not all UIViews, not all UIResponders, and not all NSObjects have the behavior of UIButton, not all UIButtons have the behavior of your custom subclass.

What you need is an instance of your subclass. What you have is an instance of UIButton.

The solution is to make that instance an instance of your subclass instead. If you created the button in Interface Builder, select the button and press ⌘6, then change the instance's Custom Class there. If you're creating the button in code, send your alloc message to your custom subclass, not directly to UIButton.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜