Subclassing UIButton but can't access my properties

强颜欢笑 提交于 2019-11-27 22:52:33

问题


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 missed something really obvious. It feels like it :)

Thanks in advance for any help you can provide

Ross


回答1:


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



回答2:


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 :-)




回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/2920045/subclassing-uibutton-but-cant-access-my-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!