iOS Runtime实现给一个扩展类添加属性

项目中我们非常多的使用类扩展,即  Category 类别,我们可以在类别中扩展很多需要的方法。 那如果需要扩展属性呢? 如果按照正常的给类添加 @property 属性,然后实现 set/get 方法,则会出现报错。 这里直接上正确的添加方式。

首先创建一个 RuntimeTest 的 Demo, 然后在 Demo 中创建一个 NSObject 的扩展类 NSObject+Extensions ,我们将在这个类别中动态添加属性。 然后 将这个类添加到 .pch 中,这样一来所有继承 NSObject 的类,都拥有动态添加的属性。 具体类目中的代码:

 

#import <Foundation/Foundation.h>

@interface NSObject (Extensions)

@property (nonatomic, copy) NSString *stringProperty;           // 扩展字符串属性

@property (nonatomic, assign) NSInteger integerProperty;        // 扩展整形属性

@property (nonatomic, assign) BOOL boolProperty;                // 扩展BOOL属性

@end

 


#import "NSObject+Extensions.h"
#import <objc/runtime.h>

// 扩展属性 对应的地址值, 保证 set/get 方法内使用的 地址完全一样。

static const void *stringPropertyKey = &stringPropertyKey;
static const void *integerPropertyKey = &integerPropertyKey;
static const void *boolPropertyKey = &boolPropertyKey;


@implementation NSObject (Extensions)

- (void)setStringProperty:(NSString *)stringProperty {
    /**
     *  根据某个对象,还有key,还有对应的策略(copy,strong等) 动态的将值设置到这个对象的key上
     *
     *  @param object 某个对象
     *  @param key    属性名,根据key去获取关联的对象, 是一个字符串常亮,是一个地址(这里注意,地址必须是不变的,地址不同但是内容相同的也不算同一个key)
     *  @param value  要设置的值
     *  @param policy 策略(copy,strong,assign等)
     */
    
    objc_setAssociatedObject(self, stringPropertyKey, stringProperty, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)stringProperty {
    return objc_getAssociatedObject(self, stringPropertyKey);
}


- (void)setIntegerProperty:(NSInteger)integerProperty {
    // 写法一
    NSNumber *number = [[NSNumber alloc] initWithInteger:integerProperty];
    objc_setAssociatedObject(self, integerPropertyKey, number, OBJC_ASSOCIATION_ASSIGN);
    
    // 写法二 (NSNumber 的创建简写)
//    objc_setAssociatedObject(self, integerPropertyKey, @(integerProperty), OBJC_ASSOCIATION_ASSIGN);
}

- (NSInteger)integerProperty {
    return [objc_getAssociatedObject(self, integerPropertyKey) integerValue];
}


- (void)setBoolProperty:(BOOL)boolProperty {
    objc_setAssociatedObject(self, boolPropertyKey, @(boolProperty), OBJC_ASSOCIATION_ASSIGN);
}

- (BOOL)boolProperty {
    return [objc_getAssociatedObject(self, boolPropertyKey) boolValue];
}

@end

主要的原理是,在 Set 方法中使用 objc_setAssociatedObject() 函数 , Get 方法中使用 objc_getAssociatedObject() 函数。 需要注意的是 objc_setAssociatedObject(object ,key,value,policy) 函数中,第二个参数 key  和 objc_getAssociatedObject(object ,key) 函数中 第二个参数 key 地址一定要相同才行。 具体代码中也有相应的注释。   类目实现完成之后,可以做一下测试。

在 ViewController 中添加 跳转到测试页面 PageViewController, 在创建 PageViewController 时,使用动态属性,并给予赋值。

#import "ViewController.h"
#import "PageViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"Home";
}

- (IBAction)gotoPageVC:(UIButton *)sender {
    
    PageViewController *vc = [[PageViewController alloc] init];
    
    vc.stringProperty = @"PageViewController";
    vc.integerProperty = 333333;
    vc.boolProperty = NO;
    
    [self.navigationController pushViewController:vc animated:YES];
}

@end

 

然后再在 PageViewController.m 中, viewDidLoad 实现输出这几个动态的参数值,并且 额外做一组测试,创建 NSArray 数组 array, 也使用动态属性赋值,并实时输出进行测试。

#import "PageViewController.h"

@interface PageViewController ()

@end

@implementation PageViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"PageViewController";
    self.view.backgroundColor = [UIColor whiteColor];
    
    // UIViewController 使用的扩展属性
    NSLog(@"stringProperty: %@", self.stringProperty);
    NSLog(@"integerProperty: %ld", self.integerProperty);
    NSLog(@"boolProperty: %d", self.boolProperty);
    
    
    // NSArray 使用扩展属性
    NSArray *array = [NSArray new];
    array.stringProperty = @"array";
    array.integerProperty = 11111;
    array.boolProperty = YES;
    
    NSLog(@"array-stringProperty: %@", array.stringProperty);
    NSLog(@"array-integerProperty: %ld", array.integerProperty);
    NSLog(@"array-boolProperty: %d", array.boolProperty);
}

@end

最后输出的结果:

 

测试Demo下载

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值