前言
添加新的執行個體變量的原理:利用category結合runtime的API實作
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsAjMfd3bkFGazxCMx8VesATMfhHLlN3XnxCMz8FdsYkRGZkRG9lcvx2bjxSa2EWNhJTW1AlUxEFeVRUUfRHelRHL2EzXlpXazxyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3PwJWZ35SO4IjN4QWOklzYmJzY2MTYyYzXxEzNwADMxEzLcZDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.webp)
動态建立屬性的應用場景:利用屬性進行傳值的時候,我們就可以利用本文的方法進行動态建立屬性。尤其在逆向其他app的時候,往已經存在class新增一個屬性,用于資料傳遞,尤其是異步操作的時候。
I 添加新的執行個體變量
1.1 原理
利用 runtime API
objc_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
//
#import "Teacher+Profession.h"
#import <objc/runtime.h>
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
#import "WCNewCommitViewController.h"
@interface NSObject (KNWCNewCommitViewControllerAssociatedObject)
// isa (Class): NSKVONotifying_WCNewCommitViewController (isa, 0x5a10db2abf7)
@property (nonatomic, strong) id associatedObject;
@end
WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.m
#import "WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.h"
@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:
#import "WCNewCommitViewController+KNWCNewCommitViewControllerAssociatedObject.h"
[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、動态添加/交換方法的實作
- Objective-C 運作時以及 Swift 的動态性
- knpost