子类化UIButton但无法访问我的属性

时间:2010-05-27 09:52:02

标签: objective-c cocoa cocoa-touch uibutton subclass

我创建了一个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;

localAnnotation是一个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类来设置该注释属性。我错过了一些非常明显的东西。感觉就好了:))

提前感谢您提供的任何帮助

罗斯

4 个答案:

答案 0 :(得分:14)

UIButton是一个类集群,这意味着Apple的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的模拟器中):< / p>

// 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

答案 1 :(得分:2)

我做了与原始海报相同的尝试,但似乎将UIButton子类化做这样的事情很难。

我做了什么,这是一个黑客 - 但现在对我有用,是添加一个UITextField作为UIButton的子视图。 UITextField没有框架并且是隐藏的,但我可以在textfield的text属性中自由存储文本字符串。这就是我想要做的......

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的子视图添加到按钮中。

哈哈: - )

答案 2 :(得分:1)

这个例外是因为你试图从中获取注释的实际按钮是MyDetailButton类的不是,它是一个UIButton。验证是否在IB中为该特定按钮设置了类。选择IB中的按钮,然后按⌘4查看其身份,将Class Identity更改为MyDetailButton。

答案 3 :(得分:0)

仅仅制作一个子类是不够的;子类不取代它的超类。同样的方式并非所有的UIControl,不是所有的UIViews,不是所有的UIResponder,也不是所有的NSObject都有UIButton的行为,并不是所有的UIButton都有自定义子类的行为。

您需要的是您的子类的实例。你拥有的是UIButton的一个实例。

解决方案是将该实例改为子类的实例。如果在Interface Builder中创建了按钮,请选择按钮并按⌘6,然后在那里更改实例的自定义类。如果您在代码中创建按钮,请将alloc消息发送到自定义子类,而不是直接发送到UIButton。