Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何生成动态属性getter/setter?_Objective C - Fatal编程技术网

Objective c 如何生成动态属性getter/setter?

Objective c 如何生成动态属性getter/setter?,objective-c,Objective C,我想在运行时添加一个属性实现方法。添加我使用+resolveInstanceMethod,class\u addMethod来执行。但是在下面的代码中,在dynamicN()和dynamicSetN()中,它们不能被编译,我不知道如何使用C函数来设置/获取没有synthesis属性的实例变量 #import <Foundation/Foundation.h> #import <objc/runtime.h> float dynamicN(id self, SEL _cm

我想在运行时添加一个属性实现方法。添加我使用+resolveInstanceMethod,class\u addMethod来执行。但是在下面的代码中,在dynamicN()和dynamicSetN()中,它们不能被编译,我不知道如何使用C函数来设置/获取没有synthesis属性的实例变量

#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;
}
#导入
#进口
浮动动态(id self,SEL\u cmd)
{
NSString*methodName=NSStringFromSelector(_cmd);
NSLog(@“%@,%@”,方法名,[自我描述]);
//返回[selfn];
}
无效动态设置(id self、SEL\u cmd、float sname)
{
printf(“setName开始;\n”);
//self.n=sname;
}
@接口bird:NSObject
{
内部高度;
浮动n;
}
@财产浮动n;
@属性int高度;
@结束
@执行鸟
@综合高度=高度;
@动态氮;
-(id)init
{
if(self=[super init]){
n=1.0;
高度=3;
}
回归自我;
}
-(浮动)n{
返回n;
}
+(BOOL)resolveInstanceMethod:(SEL)aSEL
{
如果(aSEL=@选择器(n)){
//class_addMethod([self class],aSEL,(IMP)dynamicN,“f@:”);
//返回YES;
}
如果(aSEL=@选择器(setN:){
class_addMethod([self class],aSEL,(IMP)dynamicSetN,“v:f”);
返回YES;
}
返回[super-resolveInstanceMethod:aSEL];
}
@结束
int main(int argc,const char*argv[]
{
NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];
bird*aBird=[[bird alloc]init];
aBird.n=3;
printf(“\n%f\n,%d”,aBird.n,aBird.height);
[泳池排水沟];
返回0;
}

您的setter将无法编译,因为您的
self
参数的类型为“id”,其本身没有名为“n”的属性。您将要强制转换,然后直接取消引用它:

((bird *)self)->n = sname;

虽然你的getter看起来不错,但我不知道为什么它不能被编译。

@H2CO3关于你的setter是正确的。动态getter也有同样的基本问题。您正在尝试调用
[self n]
,而
id
上不存在该命令。这就是它无法编译的原因。(正如@H2CO3所指出的,这将生成一个警告,而不是一个错误;你们都在使用
-Werror
,对吗?)但更重要的是,即使它这样做了,这将是一个无限循环
self.n
只是对
[self n]
的调用,它将被分派回该函数

如果您正在寻找示例,可以下载的第20章的代码。在
Person
项目中查找
Person.m
。如果您感兴趣,第28章将包含更多关于如何实现此类功能的说明


请注意,在ObjC中正确命名非常重要。你的类应该是
Bird
,而不是
Bird
。在尝试诸如动态分派之类的高级功能之前,掌握命名基础知识是至关重要的。

getter会自动调用,并且在运行时无法工作。需要进行与setter相同的字段访问,才能在那里获取返回值。我不明白为什么它也不会编译。类型“id”在语法上没有名为“n”的属性。编译器不知道它实际上响应了-n或-setN:methods(这是动态性的代价),这是否意味着(id)-动态类型绑定的使用不同于C函数中的静态类型?objective-c方法中的静态类型和动态类型之间是否存在一些差异?请添加从编译器中获得的错误消息。