分类是不能合成属性的,因为合成属性会生成对应的实例变量,而分类是不允许添加实例变量的(实例变量所在内存区域已初始化为不可更改,无法在动态运行时修改之)。
虽然不能增加实例变量,但是添加属性还是可以的,只不过需要自己在分类中实现get和set方法,同时标记属性为动态获取。
其中一种方法叫做关联引用,实现了用存取器来访问属性,当然实际上并没有实例变量,所以本质上只不过是增加了两个方法而已。
首先在.h中声明属性:
- #import <UIKit/UIKit.h>
-
- @interface UIViewController (PropertyTest)
- @property (nonatomic, copy) NSString *testProperty;
- @end
然后在.m中实现:
- #import "UIViewController+PropertyTest.h"
- #import <objc/runtime.h>
-
- const char kTestProperty;
-
- @implementation UIViewController (PropertyTest)
-
- @dynamic testProperty;
-
- - (void)setTestProperty:(NSString *)testProperty{
- objc_setAssociatedObject(self, &kTestProperty, testProperty, OBJC_ASSOCIATION_COPY_NONATOMIC);
- }
-
- - (NSString *)testProperty{
- return objc_getAssociatedObject(self, &kTestProperty);
- }
-
- @end
然后用代码测试一下:
- self.testProperty = @"testProperty";
- self.testProperty = [self.testProperty stringByAppendingString:@"add string"];
- NSLog(@"%@", self.testProperty);
打印如下:
- 2015-05-17 15:12:36.816 Test_5_17[3508:1209580] testPropertyadd string
可见实现了属性的get和set功能。
=====================================================================================================
给NSString类添加两种类型的属性, 字符串类型的tag值strFlag, 以及int型的tag值intTag.
定义这个两个属性的set和get方法:
- <span style="font-size:18px;">@interface NSString (Ass)
-
-
- - (void)setStrFlag:(NSString *)strFlag;
- - (NSString *)strFlag;
-
-
- - (void)setIntFlag:(int)intFlag;
- - (int)intFlag;
-
- @end</span>
实现这四个方法:
需导入runtime头文件:
- @implementation NSString (Ass)
-
- static int _intFlag;
-
- static NSString *_strFlag;
-
- - (void)setStrFlag:(NSString *)flag {
-
- objc_setAssociatedObject(self, &_strFlag, flag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
-
- - (NSString *)strFlag {
-
- return objc_getAssociatedObject(self, &_strFlag);
- }
-
- - (void)setIntFlag:(int)intFlag {
- NSNumber *t = @(intFlag);
-
- objc_setAssociatedObject(self, &_intFlag, t, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (int)intFlag {
-
- NSNumber *t = objc_getAssociatedObject(self, &_intFlag);
- return (int)[t integerValue];
- }
-
- @end
使用规则和类别差不多, 一个是拓展了方法, 一个是拓展了属性而已:
- NSString *str = @"Macro ";
- str.strFlag = @"abc";
- str.intFlag = 456;
- NSLog(@"%@:%@-%d", str, str.strFlag, str.intFlag);
工程源码