我想在运行时添加属性实现方法。添加我使用+ resolveInstanceMethod,class_addMethod来做。但是在代码下面,在dynamicN()和dynamicSetN()中,它们无法编译,我不知道如何在没有synthesize属性的情况下使用C-Function来设置/获取实例变量。
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
float dynamicN(id self, SEL _cmd)
{
NSString *methodName = NSStringFromSelector(_cmd);
NSLog(@"%@,%@", methodName, [self description]);
// return [self n];
}
void dynamicSetN(id self, SEL _cmd, float sname)
{
printf("setName start;\n");
// self.n = sname;
}
@interface bird : NSObject
{
int height;
float n;
}
@property float n;
@property int height;
@end
@implementation bird
@synthesize height = height;
@dynamic n;
- (id)init
{
if (self = [super init]) {
n = 1.0;
height = 3;
}
return self;
}
- (float) n {
return n;
}
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
{
if (aSEL == @selector(n)) {
//class_addMethod([self class], aSEL, (IMP) dynamicN, "f@:");
//return YES;
}
if (aSEL == @selector(setN:)) {
class_addMethod([self class], aSEL, (IMP) dynamicSetN, "v@:f");
return YES;
}
return [super resolveInstanceMethod:aSEL];
}
@end
int main(int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
bird *aBird = [[bird alloc] init];
aBird.n = 3;
printf("\n%f\n,%d", aBird.n, aBird.height);
[pool drain];
return 0;
}
答案 0 :(得分:2)
您的setter将无法编译,因为您的self
参数的类型为“id”,它本身没有名为“n”的属性。你会想要直接取消引用它:
((bird *)self)->n = sname;
你的getter似乎很好,我不知道为什么它不能被编译。
答案 1 :(得分:2)
@ H2CO3对你的二传手是正确的。动态吸气器具有相同的基本问题。您正在尝试拨打[self n]
,id
上不存在-Werror
。 这就是为什么它不能编译。(正如@ H2CO3所说,这会产生警告,而不是错误;你们都在使用self.n
,对吗?)但更重要的是,甚至如果确实如此,这将是一个无限循环。 [self n]
只是对Person
的调用,它将调度回此函数。
如果您正在寻找示例,可以下载iOS 6 Programming Pushing the Limits第20章的代码。查看Person.m
项目Bird
。如果您有兴趣,第28章将详细介绍如何实现此类功能。
请注意,ObjC中的正确命名非常重要。您的课程应该是bird
,而不是{{1}}。在尝试动态调度等高级功能之前,掌握命名基础是至关重要的。