通过runtime获取对象相关信息

在这里,本人给大家提供一个runtime关于NSObject的扩展,用来显示各种NSObject中的信息,这有助于你来分析类的组成:)

先准备以下类供测试:

Model.h 与 Model.m

//
// Model.h
// Runtime
//
// Copyright (c) 2014年 Y.X. All rights reserved.
// #import <Foundation/Foundation.h> typedef enum : NSUInteger {
male,
female,
} ModelSex; @interface Model : NSObject @property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, assign) ModelSex sex; - (void)info;
+ (void)className; @end
//
// Model.m
// Runtime
//
// Copyright (c) 2014年 Y.X. All rights reserved.
// #import "Model.h" @implementation Model - (void)info
{
NSLog(@"info");
} + (void)className
{
NSLog(@"Model");
} @end

以下是NSObject关于runtime的扩展category

NSObject+Runtime.h 与 NSObject+Runtime.m

//
// NSObject+Runtime.h
// Runtime
//
// Copyright (c) 2014年 Y.X. All rights reserved.
// #import <Foundation/Foundation.h> @interface NSObject (Runtime) /* ------------------------------------ */
// 获取当前类所有的子类
+ (NSArray *)runtimeSubClasses;
- (NSArray *)runtimeSubClasses; // 获取当前类所有的父类继承关系
+ (NSString *)runtimeParentClassHierarchy;
- (NSString *)runtimeParentClassHierarchy;
/* ------------------------------------ */ /* ------------------------------------ */
// 获取当前类类方法
+ (NSArray *)runtimeClassMethods;
- (NSArray *)runtimeClassMethods; // 获取当前类实例方法
+ (NSArray *)runtimeInstanceMethods;
- (NSArray *)runtimeInstanceMethods;
/* ------------------------------------ */ /* ------------------------------------ */
// 获取当前类实例变量大小
+ (size_t)runtimeInstanceSize;
- (size_t)runtimeInstanceSize; // 获取当前类的所有属性
+ (NSArray *)runtimeProperties;
- (NSArray *)runtimeProperties;
/* ------------------------------------ */ // 获取当前类继承的所有协议
+ (NSArray *)runtimeProtocols;
- (NSArray *)runtimeProtocols; @end
//
// NSObject+Runtime.m
// Runtime
//
// Copyright (c) 2014年 Y.X. All rights reserved.
// #import "NSObject+Runtime.h"
#import <objc/runtime.h> static void getSuper(Class class, NSMutableString *result)
{
[result appendFormat:@" -> %@", NSStringFromClass(class)];
if ([class superclass]) { getSuper([class superclass], result); }
} @interface NSString (Runtime)
+ (NSString *)decodeType:(const char *)cString;
@end @implementation NSString (Runtime) + (NSString *)decodeType:(const char *)cString {
if (!strcmp(cString, @encode(id))) return @"id";
if (!strcmp(cString, @encode(void))) return @"void";
if (!strcmp(cString, @encode(float))) return @"float";
if (!strcmp(cString, @encode(int))) return @"int";
if (!strcmp(cString, @encode(BOOL))) return @"BOOL";
if (!strcmp(cString, @encode(char *))) return @"char *";
if (!strcmp(cString, @encode(double))) return @"double";
if (!strcmp(cString, @encode(Class))) return @"class";
if (!strcmp(cString, @encode(SEL))) return @"SEL";
if (!strcmp(cString, @encode(unsigned int))) return @"unsigned int";
NSString *result = [NSString stringWithCString:cString encoding:NSUTF8StringEncoding];
if ([[result substringToIndex:] isEqualToString:@"@"] && [result rangeOfString:@"?"].location == NSNotFound) {
result = [[result substringWithRange:NSMakeRange(, result.length - )] stringByAppendingString:@"*"];
} else
if ([[result substringToIndex:] isEqualToString:@"^"]) {
result = [NSString stringWithFormat:@"%@ *",
[NSString decodeType:[[result substringFromIndex:] cStringUsingEncoding:NSUTF8StringEncoding]]];
}
return result;
} @end @implementation NSObject (Runtime) - (NSArray *)runtimeProperties
{
return [[self class] runtimeProperties];
} + (NSArray *)runtimeProperties
{
unsigned int outCount;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
NSMutableArray *result = [NSMutableArray array];
for (int i = ; i < outCount; i++) {
[result addObject:[self formattedPropery:properties[i]]];
}
free(properties);
return result.count ? [result copy] : nil;
} - (NSString *)runtimeParentClassHierarchy
{
return [[self class] runtimeParentClassHierarchy];
} + (NSString *)runtimeParentClassHierarchy
{
NSMutableString *result = [NSMutableString string];
getSuper([self class], result);
return result;
} - (NSArray *)runtimeSubClasses
{
return [[self class] runtimeSubClasses];
} + (NSArray *)runtimeSubClasses
{
Class *buffer = NULL; int count, size;
do
{
count = objc_getClassList(NULL, );
buffer = (Class *)realloc(buffer, count * sizeof(*buffer));
size = objc_getClassList(buffer, count);
} while(size != count); NSMutableArray *array = [NSMutableArray array];
for(int i = ; i < count; i++)
{
Class candidate = buffer[i];
Class superclass = candidate;
while(superclass)
{
if(superclass == self)
{
[array addObject: candidate];
break;
}
superclass = class_getSuperclass(superclass);
}
}
free(buffer);
return array;
} - (size_t)runtimeInstanceSize
{
return [[self class] runtimeInstanceSize];
} + (size_t)runtimeInstanceSize
{
return class_getInstanceSize(self);
} - (NSArray *)runtimeClassMethods
{
return [[self class] runtimeClassMethods];
} + (NSArray *)runtimeClassMethods
{
return [self methodsForClass:object_getClass([self class]) typeFormat:@"+"];
} - (NSArray *)runtimeInstanceMethods
{
return [[self class] runtimeInstanceMethods];
} + (NSArray *)runtimeInstanceMethods
{
return [self methodsForClass:[self class] typeFormat:@"-"];
} - (NSArray *)runtimeProtocols
{
return [[self class] runtimeProtocols];
} + (NSArray *)runtimeProtocols
{
unsigned int outCount;
Protocol * const *protocols = class_copyProtocolList([self class], &outCount); NSMutableArray *result = [NSMutableArray array];
for (int i = ; i < outCount; i++) {
unsigned int adoptedCount;
Protocol * const *adotedProtocols = protocol_copyProtocolList(protocols[i], &adoptedCount);
NSString *protocolName = [NSString stringWithCString:protocol_getName(protocols[i]) encoding:NSUTF8StringEncoding]; NSMutableArray *adoptedProtocolNames = [NSMutableArray array];
for (int idx = ; idx < adoptedCount; idx++) {
[adoptedProtocolNames addObject:[NSString stringWithCString:protocol_getName(adotedProtocols[idx]) encoding:NSUTF8StringEncoding]];
}
NSString *protocolDescription = protocolName; if (adoptedProtocolNames.count) {
protocolDescription = [NSString stringWithFormat:@"%@ <%@>", protocolName, [adoptedProtocolNames componentsJoinedByString:@", "]];
}
[result addObject:protocolDescription];
//free(adotedProtocols);
}
//free((__bridge void *)(*protocols));
return result.count ? [result copy] : nil;
} #pragma mark - Private + (NSArray *)methodsForClass:(Class)class typeFormat:(NSString *)type {
unsigned int outCount;
Method *methods = class_copyMethodList(class, &outCount);
NSMutableArray *result = [NSMutableArray array];
for (int i = ; i < outCount; i++) {
NSString *methodDescription = [NSString stringWithFormat:@"%@ (%@)%@",
type,
[NSString decodeType:method_copyReturnType(methods[i])],
NSStringFromSelector(method_getName(methods[i]))]; NSInteger args = method_getNumberOfArguments(methods[i]);
NSMutableArray *selParts = [[methodDescription componentsSeparatedByString:@":"] mutableCopy];
NSInteger offset = ; //1-st arg is object (@), 2-nd is SEL (:) for (int idx = offset; idx < args; idx++) {
NSString *returnType = [NSString decodeType:method_copyArgumentType(methods[i], idx)];
selParts[idx - offset] = [NSString stringWithFormat:@"%@:(%@)arg%d",
selParts[idx - offset],
returnType,
idx - ];
}
[result addObject:[selParts componentsJoinedByString:@" "]];
}
free(methods);
return result.count ? [result copy] : nil;
} + (NSArray *)formattedMethodsForProtocol:(Protocol *)proto required:(BOOL)required instance:(BOOL)instance {
unsigned int methodCount;
struct objc_method_description *methods = protocol_copyMethodDescriptionList(proto, required, instance, &methodCount);
NSMutableArray *methodsDescription = [NSMutableArray array];
for (int i = ; i < methodCount; i++) {
[methodsDescription addObject:
[NSString stringWithFormat:@"%@ (%@)%@",
instance ? @"-" : @"+", @"void",
NSStringFromSelector(methods[i].name)]];
} free(methods);
return [methodsDescription copy];
} + (NSString *)formattedPropery:(objc_property_t)prop {
unsigned int attrCount;
objc_property_attribute_t *attrs = property_copyAttributeList(prop, &attrCount);
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
for (int idx = ; idx < attrCount; idx++) {
NSString *name = [NSString stringWithCString:attrs[idx].name encoding:NSUTF8StringEncoding];
NSString *value = [NSString stringWithCString:attrs[idx].value encoding:NSUTF8StringEncoding];
[attributes setObject:value forKey:name];
}
free(attrs);
NSMutableString *property = [NSMutableString stringWithFormat:@"@property "];
NSMutableArray *attrsArray = [NSMutableArray array]; //https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW5
[attrsArray addObject:[attributes objectForKey:@"N"] ? @"nonatomic" : @"atomic"]; if ([attributes objectForKey:@"&"]) {
[attrsArray addObject:@"strong"];
} else if ([attributes objectForKey:@"C"]) {
[attrsArray addObject:@"copy"];
} else if ([attributes objectForKey:@"W"]) {
[attrsArray addObject:@"weak"];
} else {
[attrsArray addObject:@"assign"];
}
if ([attributes objectForKey:@"R"]) {[attrsArray addObject:@"readonly"];}
if ([attributes objectForKey:@"G"]) {
[attrsArray addObject:[NSString stringWithFormat:@"getter=%@", [attributes objectForKey:@"G"]]];
}
if ([attributes objectForKey:@"S"]) {
[attrsArray addObject:[NSString stringWithFormat:@"setter=%@", [attributes objectForKey:@"G"]]];
} [property appendFormat:@"(%@) %@ %@",
[attrsArray componentsJoinedByString:@", "],
[NSString decodeType:[[attributes objectForKey:@"T"] cStringUsingEncoding:NSUTF8StringEncoding]],
[NSString stringWithCString:property_getName(prop) encoding:NSUTF8StringEncoding]];
return [property copy];
} @end

以下是使用情形:

//
// AppDelegate.m
// Runtime
//
// Copyright (c) 2014年 Y.X. All rights reserved.
// #import "AppDelegate.h"
#import "NSObject+Runtime.h"
#import "Model.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"%@", [Model runtimeClassMethods]);
NSLog(@"%@", [Model runtimeInstanceMethods]);
NSLog(@"%@", [Model runtimeProperties]);
NSLog(@"%@", [Model runtimeParentClassHierarchy]);
NSLog(@"%@", [Model runtimeSubClasses]); return YES;
} @end

打印信息如下:

Runtime[43597:60b] (
    "+ (void)className"
)
Runtime[43597:60b] (
    "- (id)age",
    "- (void)setAge:(id)arg0 ",
    "- (unsigned int)sex",
    "- (void)setSex:(unsigned int)arg0 ",
    "- (void)setName:(id)arg0 ",
    "- (void).cxx_destruct",
    "- (id)name",
    "- (void)info"
)
Runtime[43597:60b] (
    "@property (nonatomic, strong) NSString* name",
    "@property (nonatomic, strong) NSNumber* age",
    "@property (nonatomic, assign) unsigned int sex"
)
Runtime[43597:60b]  -> Model -> NSObject
Runtime[43597:60b] (
    Model
)

以下是一些注意一点的地方:

每一个类均有一个类方法和实例变量方法相互对应

 

通过runtime获取对象相关信息的更多相关文章

  1. 获取系统相关信息 (CPU使用率 内存使用率 系统磁盘大小)

    引言 在软件开个过程中,对于软件的稳定性和使用率也是我们需要关注的 .  使用sigar来监控,简单方便!  使用说明:下载sigar jar及配合sigar的dll文件来用,需要将dll文件放到JD ...

  2. Linux sysinfo获取系统相关信息

    Linux中,可以用sysinfo来获取系统相关信息. #include <stdio.h> #include <stdlib.h> #include <errno.h& ...

  3. PHP获取手机相关信息

    该PHP操作类实现获取手机号手机头信息,取UA,取得手机类型,判断是否是opera,判断是否是m3gate,取得HA,取得手机IP 代码如下: <?php /** * @desc 手机操作类 获 ...

  4. Python基础:获取平台相关信息

    Windows 10家庭中文版,Python 3.6.4, 本文介绍了使用os.platform.sys三个模块获取Python程序的运行平台相关的信息. os模块:提供 各种各样的操作系统接口 os ...

  5. 获取IP相关信息和文件上传

    获取IP相关信息 要获取用户访问者的IP地址相关信息,可以利用依赖注入,获取IHttpConnectionFeature的实例,从该实例上可以获取IP地址的相关信息,实例如下: var connect ...

  6. iOS获取手机相关信息

    iOS具体的设备型号: #include <sys/types.h> #include <sys/sysctl.h> - (void)test { //手机型号. size_t ...

  7. ios开发-获取手机相关信息

    今天在做客户端的时候,里面有个意见反馈功能. 调用系统带的邮件功能,发送邮件到指定邮箱. 然后我就想,应该在邮件正文部分添加手机相关内容,比如型号,版本,应用程序的版本等等,这样不仅使用者方便,开发者 ...

  8. Android根据文件路径使用File类获取文件相关信息

    Android通过文件路径如何得到文件相关信息,如 文件名称,文件大小,创建时间,文件的相对路径,文件的绝对路径等: 如图: 代码: public class MainActivity extends ...

  9. android--------根据文件路径使用File类获取文件相关信息

    Android通过文件路径如何得到文件相关信息,如 文件名称,文件大小,创建时间,文件的相对路径,文件的绝对路径等. 如图: public class MainActivity extends Act ...

随机推荐

  1. mysql修改存储过程的权限

    直接上代码 grant execute on procedure 表名.存储过程名(eg: student.find) to '用户名'@'host'(eg: 'volumelicense'@'%') ...

  2. Springboot集成SpringData JPA

    序 StringData JPA 是微服务框架下一款ORM框架,在微服务体系架构下,数据持久化框架,主要为SpringData JPA及Mybatis两种,这两者的具体比较,本文不做阐述,本文只简单阐 ...

  3. oracle数据同步

    随着各行业信息化水平的不断提升,各种各样的信息管理系统都被广泛使用,各系统间数据完全独立,形成了大量的信息孤岛.出于管理及决策方面的需求,实现各平台的数据同步是一个很迫切的需求,TreeSoft数据库 ...

  4. 序列化模块1 json

    ......得到一个 字符串 的结果 过程就叫序列化 字典 / 列表 / 数字 /对象 -序列化->字符串 为什么要序列化 # 1.要把内容写入文件 序列化 # 2.网络传输数据 序列化 字符串 ...

  5. Tomcat启动慢原因之二 he APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path

    Tomcat启动时提示: 信息: The APR based Apache Tomcat Native library which allows optimal performance in prod ...

  6. Firbe Channel光纤信道

    简介 中文名:网状信道 外文名:Fibre Channel 简    称:FC 光纤信道是一种高速网络技术标准(T11),主要应用于SAN(存储局域网).其拓扑结构分为三种,点到点.仲裁循环.交换结构 ...

  7. Linux安装配置mysql

    1.假设已经有mysql-5.5.10.tar.gz以及cmake-2.8.4.tar.gz两个源文件 (1)先安装cmake(mysql5.5以后是通过cmake来编译的) [root@ rhel5 ...

  8. 教程:RSS全文输出,自己动手做。(一)

    这里以PHP版为例,尽量说得通俗点吧,水平实在有限,见谅. 目前我这里所有的获取全文输出的网站大概是三种情况: 要输出的内容集中在一页上,也就是看似列表页的页面里集中了你想要的所有内容,并不需要点击“ ...

  9. box-sizing 属性

    box-sizing属性可以为三个值: content-box,border和padding不计算入width之内 padding-box,padding计算入width内 border-box,bo ...

  10. html基础-html简介-第一个网页(1)

    今天刚刚开通博客园,把我最近整理的html/css来说一下,对于初学者还是有一定的帮助. 一.先来为大家简单普及以下html (1).html英文即:hypertext markup language ...