首页 热点专区 小学知识 中学知识 出国留学 考研考公
您的当前位置:首页正文

访问私有属性&NSValue包装

2024-12-10 来源:要发发知识网

自定义类Honzon,一个私有成员变量test和一个打印方法logTest

@interface Honzon : NSObject
- (void)logTest;
@end

@interface Honzon ()
@property(nonatomic, copy)NSString *test;
@end

@implementation Honzon

- (void)logTest {
    NSLog(@"test: %@", self.test);
}

@end

KVC

Honzon *h1 = [Honzon new];
[h1 setValue:@"h1 test" forKey:@"test"];
[h1 logTest];
//-> test: h1 test

调用私有方法

通过OC的运行时,调用私有变量的setter方法

//消息发送
Honzon *h2 = [Honzon new];
if ([h2 respondsToSelector:@selector(setTest:)]) {
    [h2 performSelector:@selector(setTest:) withObject:@"h2 test"];
    NSLog(@"%@",[h2 performSelector:@selector(test)]);
    //-> h2 test
//    objc_msgSend(h2,@selector(setTest:),@"h2 test");
//    [h2 logTest];
}

[h2 logTest];
//-> test: h2 test

当然也可以获取方法列表去循环查找

Ivar

先取得ivar,然后通过object_setIvar修改成员变量的值

//runtime 获取ivar
// 获取类的所有成员变量
Honzon *h3 = [Honzon new] ;
unsigned int count = 0;//count记录变量的数量
Ivar *members = class_copyIvarList([h3 class], &count);
for (NSUInteger i = 0; i < count; i++) {
    Ivar ivar = members[i];
    // 取得属性名并转成字符串类型
    const char *memberName = ivar_getName(ivar);
    NSString *memberNameString = [NSString stringWithUTF8String:memberName];
    if ([memberNameString isEqualToString:@"_test"]) {
        // 修改属性值
        object_setIvar(h3, ivar, @"h3 test");
        break;
    }
    
}
[h3 logTest];
free(members);
//-> test: h3 test

Honzon *h4 = [Honzon new] ;
Ivar _testNameIvar = class_getInstanceVariable([h4 class], "_test");
object_setIvar(h4, _testNameIvar, @"h4 test");
[h4 logTest];
//-> test: h4 test

NSValue包装结构体

自定义结构体

struct HZStruct {
    int version;
    char *name;
};

包装结构体

struct HZStruct hzStruct  = {
    .version = 0,
    .name = "hzStruct"
};
NSValue *hz1 = [NSValue value:&hzStruct withObjCType:@encode(struct HZStruct)];

解包结构体

struct HZStruct hzStruct2;
[hz1 getValue:&hzStruct2];
NSLog(@"%d %s",hzStruct2.version,hzStruct2.name);
//-> 0 hzStruct

NSValue针对系统的部分结构体做了优化,比如valueWithRect,不用像自定义结构体这样

显示全文