前言
添加新的实例变量的原理:利用category结合runtime的API实现
动态创建属性的应用场景:利用属性进行传值的时候,我们就可以利用本文的方法进行动态创建属性。尤其在逆向其他app的时候,往已经存在class新增一个属性,用于数据传递,尤其是异步操作的时候。
I 添加新的实例变量
1.1 原理
利用 runtime APIobjc_setAssociatedObject
和objc_getAssociatedObject
objc_setAssociatedObject
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association.
* @param key The key for the association.
* @param value The value to associate with the key key for object. Pass nil to clear an existing association.
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
*
* @see objc_setAssociatedObject
* @see objc_removeAssociatedObjects
*/
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
/**
* Returns the value associated with a given object for a given key.
*
* @param object The source object for the association.
* @param key The key for the association.
*
* @return The value associated with the key \e key for \e object.
*
* @see objc_setAssociatedObject
*/
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
1.2 例子
类别(Category)
通过增加新的类和实例方法来扩展现有类的行为。作为惯例,类别被定义在它们自己的.{h,m}
文件里。
//
// Teacher+Profession.m
//
const char *ProfessionType = "NSString *"; //就是属性的key
@implementation Teacher (Profession)
-(void)setProf:(NSString*)prof
{
objc_setAssociatedObject(self, ProfessionType, prof, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)prof
{
NSString *pro = objc_getAssociatedObject(self, ProfessionType);
return pro;
}
@end
II 动态创建属性
使用分类、@dynamic
、objc_setAssociatedObject、objc_getAssociatedObject 实现。
2.1 应用场景
利用属性进行传值的时候,我们就可以利用本文的方法进行动态创建属性。尤其在逆向其他app的时候,往已经存在class新增一个属性,用于数据传递,尤其是异步操作的时候。
//结合@dynamic的 associatedObject例子
@implementation NSObject (AssociatedObject)
@dynamic associatedObject;
- (void)setAssociatedObject:(id)object {
objc_setAssociatedObject(self,
@selector(associatedObject), object,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)associatedObject {
return objc_getAssociatedObject(self,
@selector(associatedObject));
}
2.2 例子:为VC新增一个属性
WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.h
@interface NSObject (KNWCNewCommitViewControllerAssociatedObject)
// isa (Class): NSKVONotifying_WCNewCommitViewController (isa, 0x5a10db2abf7)
@property (nonatomic, strong) id associatedObject;
@end
WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.m
@implementation NSObject (KNWCNewCommitViewControllerAssociatedObject)
@dynamic associatedObject;
- (void)setAssociatedObject:(id)object {
objc_setAssociatedObject(self,
@selector(associatedObject), object,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)associatedObject {
return objc_getAssociatedObject(self,
@selector(associatedObject));
}
@end
2.3 效果
- usage:
[WCNewCommit setAssociatedObject:@"sssss"];
- ret
NSLog(@"associatedObject:%@",[self valueForKey:@"associatedObject"]);//2018-09-06 12:06:06.977711 WeChat[717:226743] associatedObject:sssss
See Also
- iOS运行时的应用:
1、实现路由(接口控制app跳任意界面 )
2、获取修改对象的成员属性
3、动态添加/交换方法的实现
4、属性关联
- Objective-C 运行时以及 Swift 的动态性
- knpost