美文网首页
iOS-Runtime-使用关联对象给Category添加成员变

iOS-Runtime-使用关联对象给Category添加成员变

作者: Simple_Code | 来源:发表于2018-09-07 14:59 被阅读41次

开发问题:需要在一个类的Category中添加属性;
实际实践:通过 Category 给一个现有的类添加属性,却不能添加实例变量;
解决方案:通过runtime建立关联引用;

image.png

从上图分类在OC源码中的结构体,可以看出里面不存在成员变量列表。因此,分类里面的属性在外边是无法通过点语法调用或者get方法的获取的,但是我们可以使用关联对象给Category添加成员变量。从而达到一般类里面属性的正常调用。下面提供四种方法:

首先介绍两个Runtime相关的关联函数:

    /**
     @param object#> 第一个参数为从该object中获取关联对象
     @param key#> 第二个参数为想要获取关联对象的key
     @param value#> 第三个参数为需要和object建立关联引用对象的value
     @param policy#> 第四个参数为关联策略,等同于给property添加关键字,具体说明如下图关联策略对应图
     */
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
                         id _Nullable value, objc_AssociationPolicy policy)

    /**
     @param object#> 第一个参数为从该object中获取关联对象
     @param key#> 第二个参数为想要获取关联对象的key
     */
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);
关联策略对应图.png

方法1:推荐使用

#import "Person.h"

@interface Person (Test)
@property (nonatomic, copy) NSString *name;
@end

#import "Person+Test.h"
#import <objc/runtime.h>

@implementation Person (Test)

- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY);
}
- (NSString *)name {
    return objc_getAssociatedObject(self, @selector(name));
}

或者

#import "Person.h"

@interface Person (Test)
@property (nonatomic, copy) NSString *name;
@end

#import "Person+Test.h"
#import <objc/runtime.h>

@implementation Person (Test)

- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY);
}
- (NSString *)name {
    return objc_getAssociatedObject(self, _cmd);
}

注:

_cmd = @selector(name) 隐式参数

方法2:

#import "Person.h"

@interface Person (Test)
@property (nonatomic, copy) NSString *name;
@end

#import "Person+Test.h"
#import <objc/runtime.h>

@implementation Person (Test)

#define SPNameKey @"name"
 - (void)setName:(NSString *)name {
 objc_setAssociatedObject(self, SPNameKey, name, OBJC_ASSOCIATION_COPY);
 }
 - (NSString *)name {
 return objc_getAssociatedObject(self, SPNameKey);
 }

注:

SPNameKey必须和该Value名称一致

方法3:

#import "Person.h"

@interface Person (Test)
@property (nonatomic, copy) NSString *name;
@end

#import "Person+Test.h"
#import <objc/runtime.h>

@implementation Person (Test)

static const char SPNameKey;
- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, &SPNameKey, name, OBJC_ASSOCIATION_COPY);
}
- (NSString *)name{
    return objc_getAssociatedObject(self, &SPNameKey);
}

方法4:

#import "Person.h"

@interface Person (Test)
@property (nonatomic, copy) NSString *name;
@end

#import "Person+Test.h"
#import <objc/runtime.h>

@implementation Person (Test)

 static const void *SPNameKey = &SPNameKey;
 
 - (void)setName:(NSString *)name {
 objc_setAssociatedObject(self, SPNameKey, name, OBJC_ASSOCIATION_COPY);
 }
 - (NSString *)name{
 return objc_getAssociatedObject(self, SPNameKey);
 }

那么如何添加Button对象?

代码如下:

@interface UIView (Test)
@property (nonatomic, strong) UIButton *hideButton;
@end

//setter
- (void)setHideButton:(UIButton *)hideButton {
    objc_setAssociatedObject(self, @selector(hideButton), hideButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//getter 
- (UIButton *)hideButton {
    UIButton *_hideButton = objc_getAssociatedObject(self, @selector(hideButton));
    if (!_hideButton) {
        _hideButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _hideButton.frame = CGRectMake(self.bounds.size.width/2-110, 260, 220, 44);
        _hideButton.backgroundColor = [UIColor brownColor];
        [_hideButton setTitle:@"Hide" forState:UIControlStateNormal];
        objc_setAssociatedObject(self, @selector(hideButton), _hideButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return _hideButton;
}

相关文章

  • iOS-Runtime-使用关联对象给Category添加成员变

    开发问题:需要在一个类的Category中添加属性;实际实践:通过 Category 给一个现有的类添加属性,却不...

  • iOS - 关联对象

    一、简介 关联对象的使用一般用于给 Category 添加成员变量。我们知道,分类添加属性只能生成 setter/...

  • 关联对象学习

    在没有介绍关联对象之前,先看一道面试题 Category能否添加成员变量?如果可以,如何给Category添加成员...

  • OC语言之category_关联对象的本质源码解析

    关联对象 能否给分类添加"成员变量"? 使用关联对象技术为分类添加"成员变量" 关联对象添加的"成员变量"添加到了...

  • iOS内存管理-week和关联对象怎么释放(2)

    关联对象可以为category添加成员变量,因为我们虽然可以通过category为类添加属性,但是只是生成了方法声...

  • 探寻关联对象实现原理

    iOS底层原理总结 - 关联对象实现原理 面试题 问: Category能否添加成员变量?如果可以,如何给Cate...

  • runtime的实际应用

    1、使用关联对象动态给分类添加属性 使用关联对象,可以为类添加Category中的属性,我们可以为现有类添加一些实...

  • iOS关联对象的源码探究

    本文探究问题:- 怎么通过关联对象为分类category添加成员变量?- 添加的成员变量被存储在哪了? 1.为分类...

  • 关联对象实现原理

    问题: Category能否添加成员变量?如果可以,如何给Category添加成员变量? 1. 给Category...

  • Runtime #2

    Category关联属性 为一个对象设置关联对象,实现为其添加属性的效果,使用方法 Method Swizzlin...

网友评论

      本文标题:iOS-Runtime-使用关联对象给Category添加成员变

      本文链接:https://www.haomeiwen.com/subject/ugrcgftx.html