12

我想在类扩展中向 UITableView 添加一个属性:

@interface UITableViewController ()

@property NSString *entityString;

@end

然后我导入扩展,然后在 UITableViewController 的子类中使用 entityString 属性:

@implementation CustomerTableViewController

- (void)viewDidLoad {
    self.entityString = @"Customer";
    ...
    [super viewDidLoad];
}
...

苹果文档说:

编译器将在主类实现中自动合成相关的访问器方法(...)。

但是当我尝试执行它时,我得到了这个错误:

-[CustomerTableViewController setEntityString:]:无法识别的选择器发送到实例 0x737b670

我究竟做错了什么?也许子类无法访问该属性?

4

3 回答 3

16

尝试使用具有关联引用的类别。它更干净,适用于 UIButton 的所有实例。

UIButton+Property.h

#import <Foundation/Foundation.h>

@interface UIButton(Property)

@property (nonatomic, retain) NSObject *property;

@end


UIButton+Property.m

#import "UIButton+Property.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_PROPERTY_KEY;

@dynamic property;

-(void)setProperty:(NSObject *)property
{
  objc_setAssociatedObject(self, &UIB_PROPERTY_KEY, property, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)property
{
   return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY);
}

@end

//示例用法

#import "UIButton+Property.h"


UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.property = @"HELLO";
NSLog(@"Property %@", button1.property);
button1.property = nil;
NSLog(@"Property %@", button1.property);
于 2012-09-03T18:57:57.957 回答
8

扩展用于声明额外的接口——方法和属性——其实现契约将在类的 primary 中得到满足@implementation

这正是您不能通过类扩展添加存储——添加 ivars 的原因。类扩展是一个接口,不多也不少。 @synthesize是为@property声明创建存储的原因,但@synthesizean@property只能出现在@implementation类中(无论是显式的还是作为编译器的默认行为)。

由于您无法重新编译框架类,因此无法向其中添加 ivars。

@prashat 的答案是向现有类添加存储的一种方法。然而,走这条路通常是不可取的。随意挂起框架类的状态是设计不佳的标志,并且随着时间的推移会使您的应用程序变得更加难以维护。

更好地重新审视您的设计,了解为什么您目前需要将状态附加到不能直接包含它的对象,然后重构该要求。

于 2012-09-03T19:42:04.670 回答
5

文档状态:

类扩展类似于匿名类别,只是它们声明的方法必须在相应类的主 @implementation 块中实现。

使用@property时,大致相当于声明访问器方法。所以这意味着你只能做这样的事情,如果你也是@implementation类的“主”块的作者,而 UITableViewController,你不是。

您在这里唯一的选择是类别,它不能添加实例变量。

文档链接,并注意该页面的最后一行:

setValue: 方法的实现必须出现在该类的主 @implementation 块中(您不能在类别中实现它)。如果不是这种情况,编译器会发出一条警告,指出它找不到 setValue: 的方法定义。

于 2012-09-03T18:55:30.503 回答