三种方式供你选择

  • 通过KVC来设置
  • 通过runtime动态改变
  • 通过 msg_send() 设置

先定义这样一个类 PrivateVariablesClass:

  1. #import "PrivateVariablesClass.h"
  2. @interface PrivateVariablesClass ()
  3. @property (nonatomic, assign) NSInteger priviteNum;
  4. @property (nonatomic, strong) UIView *priviteView;
  5. @end
  6. @implementation PrivateVariablesClass
  7. -(void)showPropertyPrivateVariablesClass
  8. {
  9. NSLog(@"priviteNum = %@", @(_priviteNum));
  10. NSLog(@"priviteView = %@", _priviteView);
  11. }
  12. @end

我们在外部改完后,调用 showPropertyPrivateVariablesClass 方法去查看这两个私有属性的值。

1.KVC:

  1. -(void)way1{
  2. PrivateVariablesClass *classA = [[PrivateVariablesClass alloc] init];
  3. [classA setValue:@(4) forKey:@"_priviteNum"];
  4. [classA setValue:self.view forKey:@"_priviteView"];
  5. [classA showPropertyPrivateVariablesClass];
  6. }

结果输出:

  1. priviteNum = 4
  2. priviteView = <UIView: 0x7fae50f07e10; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x600003c08020>>

2.runtime动态改变

  1. -(void)way2{
  2. PrivateVariablesClass *classA = [[PrivateVariablesClass alloc] init];
  3. unsigned int outCount = 0;
  4. Ivar *ivars = class_copyIvarList([PrivateVariablesClass class], &outCount);
  5. for (int i = 0; i < outCount; i ++) {
  6. Ivar ivar = ivars[i];
  7. const char *ivarName = ivar_getName(ivar);
  8. //这里要注意ARC下, 这个会报错
  9. /**
  10. 在修改NSInteger型变量的时候,ARC下,编译器不允许你将NSInteger类型的值赋值给id,在buildsetting中将Objective-C Automatic Reference Counting修改为No即可。但是这样工程就会变成MRC,所以,如果是非对象类型就不建议用object_setIvar这样的方法去修改了。
  11. */
  12. int a = strcmp(ivarName, "_priviteNum");
  13. if (strcmp(ivarName, "_priviteNum") == 0) {
  14. //这种方式传值int类型会报错,不能传入
  15. object_setIvar(classA, ivar, 22);
  16. }
  17. if (strcmp(ivarName, "_priviteView") == 0) {
  18. object_setIvar(classA, ivar, self.view);
  19. }
  20. }
  21. [classA showPropertyPrivateVariablesClass];
  22. }

结果输出:

  1. priviteNum = 22
  2. priviteView = <UIView: 0x7ffb08e0b040; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x60000398ad40>>

3.msg_send()

既然是私有属性了,必然有setter方法, 那我们动态调用一下(适用私有属性,不适用私有变量)。

  1. -(void)way3{
  2. PrivateVariablesClass *classA = [[PrivateVariablesClass alloc] init];
  3. ((void (*)(id, SEL, int))(void *) objc_msgSend)((id)classA, @selector(setPriviteNum:) , 33);
  4. ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)classA, @selector(setPriviteView:) , self.view);
  5. [classA showPropertyPrivateVariablesClass];
  6. }

结果输出:

  1. priviteNum = 33
  2. priviteView = <UIView: 0x7fd4bfa079f0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x600001085f40>>