通过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. 启动mongodb和redis服务器

    一.mongodb sudo service mongod start sudo service mongod restart sudo service mongod stop 二.redis red ...

  2. python mysql uitl

    from traceback import format_exc import pymysql as MySQLdb class MySQLUtils(object): def get_db_conn ...

  3. Linux中终端和控制台的一些不成熟的理解

    首先声明,这仅仅是在下一些不成熟的想法.是通过看网上的一些资料和自己实践的一些心得,应该都是些很不成熟甚至是不太正确的想法.但是我还是想记录下来,算是一个心路历程吧.等以后成熟了,再来修改. 首先说一 ...

  4. scanf()函数分析

    首先,先来讲一下scanf的读取流程: 从键盘输入的都是字符类型(一系列的字符),scanf()的作用就是将这个字符序列转换成一个或多个指定的类型,并保存到变量中. 从键盘输入的字符序列会先缓存到键盘 ...

  5. NodeJS调用jar包

    我们在实际的生产.开发实践中,其实要和许多第三方服务商进行打交道,这其中包括使用他们提供的批量与联机服务,但与别的互联网企业不大相同的是,银行作为传统企业,其一贯重视安全性,许多在互联网企业看似理所当 ...

  6. rpm使用方法

    查看rpm信息:rpm -q [软件的rpm名字]rpm -q下还有很多选项,具体功能如下:rpm -qa                列出所有已安装的RPM文件rpm -qa | grep [rp ...

  7. Matlab基本数学应用

    基本线性代数 [R jb]=rref(A)将A化为行最简型矩阵.R为所得行最简型矩阵,jb是一个向量显示每行首非0元所在列号. inv(A)求方阵A的逆,注意结果可能出现错误.当结果中出现Inf和Na ...

  8. java开学考试感想及代码

    上周四我们的第一节java课,王老师给我们进行啦开学考试,这也是上学期放假之前给我们约定好的 但是情况显然没有我想的那么好,其实我觉得这个atm系统比上届学生信息管理系统难的多,上届的话毕竟有小学期的 ...

  9. [转] Hadoop管理员的十个最佳实践

    前言 接触Hadoop有两年的时间了,期间遇到很多的问题,既有经典的NameNode和JobTracker内存溢出故障,也有HDFS存储小文件问题,既有任务调度问题,也有MapReduce性能问题.遇 ...

  10. 微信小程序、微信公众号、H5之间相互跳转

    转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息 ...