为了账号安全,请及时绑定邮箱和手机立即绑定

如何在运行时向对象添加属性?

如何在运行时向对象添加属性?

鸿蒙传说 2019-12-16 10:43:44
是否可以在运行时将属性添加到Objective C对象?如何在运行时向对象添加属性?
查看完整描述

3 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

可以通过class_addProperty()以下方式向类添加形式属性:


BOOL class_addProperty(Class cls,

    const char *name,

    const objc_property_attribute_t *attributes,

    unsigned int attributeCount)

前两个参数是不言自明的。第三个参数是属性的属性的阵列,并且每个属性特性是一个名称-值对,其遵循的Objective-C 型编码对声明的属性。请注意,文档中仍然提到了逗号分隔的字符串,用于属性属性的编码。逗号分隔的字符串中的每个段均由一个objc_property_attribute_t实例表示。此外,objc_property_attribute_t除了的通用@类型编码外,还接受类名称id。


这里有一个程序,动态地增加了一个叫做物业的初稿name到已被称为实例变量类_privateName:


#include <objc/runtime.h>

#import <Foundation/Foundation.h>


@interface SomeClass : NSObject {

    NSString *_privateName;

}

@end


@implementation SomeClass

- (id)init {

    self = [super init];

    if (self) _privateName = @"Steve";

    return self;

}

@end


NSString *nameGetter(id self, SEL _cmd) {

    Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");

    return object_getIvar(self, ivar);

}


void nameSetter(id self, SEL _cmd, NSString *newName) {

    Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");

    id oldName = object_getIvar(self, ivar);

    if (oldName != newName) object_setIvar(self, ivar, [newName copy]);

}


int main(void) {

    @autoreleasepool {

        objc_property_attribute_t type = { "T", "@\"NSString\"" };

        objc_property_attribute_t ownership = { "C", "" }; // C = copy

        objc_property_attribute_t backingivar  = { "V", "_privateName" };

        objc_property_attribute_t attrs[] = { type, ownership, backingivar };

        class_addProperty([SomeClass class], "name", attrs, 3);

        class_addMethod([SomeClass class], @selector(name), (IMP)nameGetter, "@@:");

        class_addMethod([SomeClass class], @selector(setName:), (IMP)nameSetter, "v@:@");


        id o = [SomeClass new];

        NSLog(@"%@", [o name]);

        [o setName:@"Jobs"];

        NSLog(@"%@", [o name]);

    }

}

其(修剪后的)输出:


Steve

Jobs

应该更加仔细地编写getter和setter方法,但这足以作为如何在运行时动态添加形式属性的示例。


查看完整回答
反对 回复 2019-12-16
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

如果您查看此处NSKeyValueCoding记录的协议,则可以看到一条消息:


- (id)valueForUndefinedKey:(NSString *)key

您应该重写该方法以为指定的undefined属性提供自定义结果。当然,这假定您的类使用相应的协议。


这种方法通常用于向类提供未知的行为(例如,不存在的选择器)。


查看完整回答
反对 回复 2019-12-16
?
暮色呼如

TA贡献1853条经验 获得超9个赞

否(即,使用点语法等)。但是您可以使用关联对象来添加存储:如何在对象内部使用objc_setAssociatedObject / objc_getAssociatedObject?。

查看完整回答
反对 回复 2019-12-16
  • 3 回答
  • 0 关注
  • 437 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信