我想在类扩展中向UITableView添加一个属性:
@interface UITableViewController ()
@property NSString *entityString;
@end
然后我导入扩展,然后在UITableViewController的子类中使用entityString属性:
@implementation CustomerTableViewController
- (void)viewDidLoad {
self.entityString = @"Customer";
...
[super viewDidLoad];
}
...
编译器将自动合成相关的访问器 主类中的方法(...) 实施
但是当我尝试执行它时,我收到了这个错误:
- [CustomerTableViewController setEntityString:]:无法识别的选择器发送到实例0x737b670
我做错了什么?也许子类无法访问该属性?
答案 0 :(得分:13)
尝试使用带有关联引用的类别。它更清晰,适用于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);
答案 1 :(得分:6)
类扩展用于声明其他接口 - 方法和属性 - 其实现合同将在类的主要@implementaiton
中得到满足。
这正是您无法通过类扩展添加存储 - 添加ivars的原因。类扩展是一个接口,不多也不少。 @synthesize
为@property
声明创建了存储空间,但@synthesize
的{{1}}只能出现在类的@property
中(无论是显式还是默认编译器的行为。)
由于您无法重新编译框架类,因此无法向其添加ivars。
@ prashat的答案是向现有类添加存储的一种方法。但是,走这条路通常是不可取的; willy-nilly框架类的悬挂状态是设计不良的标志,并且会使你的应用程序在一段时间内难以维护。
更好地重新审视您的设计,理解为什么您当前需要将状态附加到无法直接包含它的对象,并重构该要求。
答案 2 :(得分:5)
文档声明:
类扩展类似于匿名类别,除了它们声明的方法必须在相应类的主@implementation块中实现。
使用@property
时,它大致相当于声明访问器方法。所以这意味着如果你也是类的“主”@implementation
块的作者,你只能做这样的事情,而使用UITableViewController,你不是。
这里唯一的选择是类别,它无法添加实例变量。
The docs link,并注意该页面的最后一行:
setValue:方法的实现必须出现在类的主@implementation块中(您不能在类别中实现它)。如果不是这种情况,编译器会发出警告,指出它无法找到setValue的方法定义:。