6.2 蒼老師的特徵篇
蒼老師在大家心目中應該有很多特徵吧,下面我們通過代碼來獲取蒼老師的特徵。
People.h文件
@interface People : NSObject
{
NSString *_occupation;
NSString *_nationality;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic) NSUInteger age;
- (NSDictionary *)allProperties;
- (NSDictionary *)allIvars;
- (NSDictionary *)allMethods;
@end
People.m文件
#if TARGET_IPHONE_SIMULATOR
#import <objc/objc-runtime.h>
#else
#import <objc/runtime.h>
#import <objc/message.h>
#endif
@implementation People
- (NSDictionary *)allProperties
{
unsigned int count = 0;
// 獲取類的所有屬性,如果沒有屬性count就爲0
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableDictionary *resultDict = [<a href="http://www.jobbole.com/members/www821839432">@{}</a> mutableCopy];
for (NSUInteger i = 0; i < count; i ++) {
// 獲取屬性的名稱和值
const char *propertyName = property_getName(properties[i]);
NSString *name = [NSString stringWithUTF8String:propertyName];
id propertyValue = [self valueForKey:name];
if (propertyValue) {
resultDict[name] = propertyValue;
} else {
resultDict[name] = @"字典的key對應的value不能爲nil哦!";
}
}
// 這裏properties是一個數組指針,我們需要使用free函數來釋放內存。
free(properties);
return resultDict;
}
- (NSDictionary *)allIvars
{
unsigned int count = 0;
NSMutableDictionary *resultDict = [<a href="http://www.jobbole.com/members/www821839432">@{}</a> mutableCopy];
Ivar *ivars = class_copyIvarList([self class], &count);
for (NSUInteger i = 0; i < count; i ++) {
const char *varName = ivar_getName(ivars[i]);
NSString *name = [NSString stringWithUTF8String:varName];
id varValue = [self valueForKey:name];
if (varValue) {
resultDict[name] = varValue;
} else {
resultDict[name] = @"字典的key對應的value不能爲nil哦!";
}
}
free(ivars);
return resultDict;
}
- (NSDictionary *)allMethods
{
unsigned int count = 0;
NSMutableDictionary *resultDict = [<a href="http://www.jobbole.com/members/www821839432">@{}</a> mutableCopy];
// 獲取類的所有方法,如果沒有方法count就爲0
Method *methods = class_copyMethodList([self class], &count);
for (NSUInteger i = 0; i < count; i ++) {
// 獲取方法名稱
SEL methodSEL = method_getName(methods[i]);
const char *methodName = sel_getName(methodSEL);
NSString *name = [NSString stringWithUTF8String:methodName];
// 獲取方法的參數列表
int arguments = method_getNumberOfArguments(methods[i]);
resultDict[name] = @(arguments-2);
}
free(methods);
return resultDict;
}
@end
在main.m中運行以下代碼
int main(int argc, const char * argv[]) {
@autoreleasepool {
People *cangTeacher = [[People alloc] init];
cangTeacher.name = @"蒼井空";
cangTeacher.age = 18;
[cangTeacher setValue:@"老師" forKey:@"occupation"];
NSDictionary *propertyResultDic = [cangTeacher allProperties];
for (NSString *propertyName in propertyResultDic.allKeys) {
NSLog(@"propertyName:%@, propertyValue:%@",propertyName, propertyResultDic[propertyName]);
}
NSDictionary *ivarResultDic = [cangTeacher allIvars];
for (NSString *ivarName in ivarResultDic.allKeys) {
NSLog(@"ivarName:%@, ivarValue:%@",ivarName, ivarResultDic[ivarName]);
}
NSDictionary *methodResultDic = [cangTeacher allMethods];
for (NSString *methodName in methodResultDic.allKeys) {
NSLog(@"methodName:%@, argumentsCount:%@", methodName, methodResultDic[methodName]);
}
}
return 0;
}
最後的輸出結果如下:
是不是有點失望,我沒有加一些特殊的技能,留給下文了。此實戰內容是通過蒼老師的一些特徵學習:如何獲取對象所有的屬性名稱和屬性值、獲取對象所有成員變量名稱和變量值、獲取對象所有的方法名和方法參數數量。
6.3 蒼老師增加新技能篇
蒼老師要通過Category和Associated Objects增加技能了,快看!
創建People+Associated.h文件如下:
#import "People.h"
typedef void (^CodingCallBack)();
@interface People (Associated)
@property (nonatomic, strong) NSNumber *associatedBust; // 胸圍
@property (nonatomic, copy) CodingCallBack associatedCallBack; // 寫代碼
@end
People+Associated.m如下:
#import "People+Associated.h"
#if TARGET_IPHONE_SIMULATOR
#import <objc/objc-runtime.h>
#else
#import <objc/runtime.h>
#import <objc/message.h>
#endif
@implementation People (Associated)
- (void)setAssociatedBust:(NSNumber *)bust
{
// 設置關聯對象
objc_setAssociatedObject(self, @selector(associatedBust), bust, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)associatedBust
{
// 得到關聯對象
return objc_getAssociatedObject(self, @selector(associatedBust));
}
- (void)setAssociatedCallBack:(CodingCallBack)callback {
objc_setAssociatedObject(self, @selector(associatedCallBack), callback, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CodingCallBack)associatedCallBack {
return objc_getAssociatedObject(self, @selector(associatedCallBack));
}
@end
在main.m中運行以下代碼
#import "People.h"
#import "People+Associated.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
People *cangTeacher = [[People alloc] init];
cangTeacher.name = @"蒼井空";
cangTeacher.age = 18;
[cangTeacher setValue:@"老師" forKey:@"occupation"];
cangTeacher.associatedBust = @(90);
cangTeacher.associatedCallBack = ^(){
NSLog(@"蒼老師要寫代碼了!");
};
cangTeacher.associatedCallBack();
NSDictionary *propertyResultDic = [cangTeacher allProperties];
for (NSString *propertyName in propertyResultDic.allKeys) {
NSLog(@"propertyName:%@, propertyValue:%@",propertyName, propertyResultDic[propertyName]);
}
NSDictionary *methodResultDic = [cangTeacher allMethods];
for (NSString *methodName in methodResultDic.allKeys) {
NSLog(@"methodName:%@, argumentsCount:%@", methodName, methodResultDic[methodName]);
}
}
return 0;
}
這次運行結果多出了一個associatedBust(胸圍)和一個associatedCallBack(寫代碼)屬性。
如圖:
我們成功的給蒼老師添加個一個胸圍的屬性和一個寫代碼的回調,但是添加屬性沒有什麼意義,我們平時在開發過成功中用的比較多的就是添加回調了。