_cmd, objc_set(get)AssociatedObj

2018-09-12  本文已影响0人  天之鱼

1、_cmd

_cmd表示当前方法的selector的一个指针,如同self表示指向当前对象的一个指针

注意:NSString *NSStringFromSelector(SEL aSelector) 的参数就是一个SEL, 也就是说_cmd就是SEL类型。

- (void)viewDidLoad{

[super viewDidLoad];

NSLog(@"Current method: %@ %@",[self class],NSStringFromSelector(_cmd));}

输出结果如下:

 Current method: FirstViewController viewDidLoad

2、objc_setAssociatedObject

来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略。

OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
static char myKey;

objc_setAssociatedObject(self, &myKey, anObject, OBJC_ASSOCIATION_RETAIN);

self对象将获取一个新的关联的对象anObject,且内存管理策略是自动retain关联对象,当self对象释放时,会自动release关联对象。
另外,如果我们使用同一个key来关联另外一个对象时,也会自动释放之前关联的对象,这种情况下,先前的关联对象会被妥善地处理掉,并且新的对象会使用它的内存。

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                            *   The association is made atomically. */
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                            *   The association is made atomically. */
};

3. 动态添加方法及属性

objc_setAssociatedObject 添加的变量不会存在类的IVars中,而是存储在对象的Associative Referencesdictionary中;也就是说我们这样添加的变量并不改变类对象的大小。

#import <Foundation/Foundation.h>

@interface NSObject (CategoryTT)

// 添加属性, 不过不会生成成员变量, 需要手动实现getter和setter
@property(nonatomic, copy) NSString *name;
// 添加方法
- (NSString *)des;
@end


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

@implementation NSObject (CategoryTT)

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

- (NSString *)des {
    return @"这个NSObject的分类CategoryTT";
}

@end

// 测试Category的属性
    NSObject *obj= [[NSObject alloc] init];
    obj.name = @"lili";
    NSLog(@"obj name: %@", [obj name]); // obj name: lili
    
    // 分类中实现了des方法, ExtensionsAndCategory->UIViewController->NSObject(继承关系)
    NSLog(@"obj des: %@", [self des]); // obj des: 这个NSObject的分类CategoryTT

也可直接关联对象

    //** 将一个对象直接关联到NSArray对象上 */
    NSArray *array = [NSArray arrayWithObjects:@"111", @"222", @"333", nil];
    NSString *string = @"JAM";
    
    // 将string关联到array上
    objc_setAssociatedObject(array, &associatedKey, string, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    // 从array中获取被关联的对象string
    NSString *getAssociatedObject = objc_getAssociatedObject(array, &associatedKey);//string已经变成array的一个属性了
    
    NSLog(@"%@", getAssociatedObject);//输出结果:JAM

4.断开关联

5.category

Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的,在很多情形下Category也是比创建子类更优的选择。新添加的方法同样也会被被扩展的类的所有子类自动继承。当知道已有类中某个方法有BUG,但是这个类是以库的形式存在的,我们无法直接修改源代码的时候,

Category的用途

代码组织

Category用于大型类有效分解。通常一个大型类的方法可以根据某种逻辑或是相关性分解为不同的组,一个类的代码量越大,将这个类分解到不同的文件中就显得越有用,每个文件中分别是这个类的某些相关方法的集合。

当有多个开发者共同完成一个项目时,每个人所承担的是单独的cagegory的开发和维护。这样就版本控制就更加简单了,因为开发人员之间的工作冲突更少了。

Category VS 添加子类

并没有什么界限分明的判定标准来作为何时用Category何时用添加子类的方法的指导。但是有以下几个指导性的建议:

Category 不添加成员变量

扩展(Extension)

总结

参考

上一篇 下一篇

猜你喜欢

热点阅读