iOS 关联引用为分类添加属性

开发者可以使用关联引用为任何对象附着键值数据.

使用关联引用为分类添加属性, 首先, 我们新建一个Person类, Person.h的文件如下

//Person.h
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (copy, nonatomic) NSString *name;

@end

`Person`类的实现文件如下:

//Person.m
#import "Person.h"

@implementation Person

@end

现在, 我们在Person的分类中添加新的属性emailAddress, 现在头文件中使用@property声明这个属性.

//Person+EmailAddress.h 
#import "Person.h"

@interface Person (EmailAddress)

@property (copy, nonatomic) NSString *emailAddress;

@end

当我们只在分类的.h文件中加入属性的时候, 会产生如下的警告.

Property 'emailAddress' requires method 'setEmailAddress:' to be defined - use @dynamic or provide a method implementation in this category.

这时, 我们使用objc/Runtime库中的动态方法为生成获取和设置属性的方法.

id objc_getAssociatedObject(id object, void *key)

void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)

Person+emailAddress.m方法的实现代码如下

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

@implementation Person (EmailAddress)

static char emailAddressKey;

- (NSString *)emailAddress {
    return objc_getAssociatedObject(self, &emailAddressKey);
}

- (void)setEmailAddress:(NSString *)emailAddress {
    objc_setAssociatedObject(self, &emailAddressKey,
                             emailAddress, OBJC_ASSOCIATION_COPY);
}

@end

注意:

  1. emailAddressKey的声明方法, 使用static char.
  2. emailAddressKey这个名字并不重要, 它与我们实际使用的属性emailAddress的名字无关,这里加入后缀Key仅仅为了code的整洁
  3. 我们使用OBJC_ASSOCIATION_COPY等参数作为语义管理,正确处理copy, assign, retain等语义.

Draveness

iOS Developer / Rails / Elixir

Maine, USA draveness.me
blog comments powered by Disqus