总结:
Classget 类名,父类;实例变量;属性;实例方法,类方法,方法实现;
Copy 实例变量列表;属性列表;协议列表;方法列表
Add 实例变量,属性,协议,方法
replace 方法;属性
responds 响应方法
conforms 实现协议
Objc
get 类,实例变量,实例变量的值,元类,协议,关联对象,类列表
copy 类列表,协议列表
set 实例变量,类,实例变量的值
一、runtime 文档
源码github: objc-runtime
官方API: Objective-C Runtime
二、类的本质
1、对象:含有 isa指针的结构体
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// Represents an instance of a class. 表示类的实例
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.指向类实例的指针
typedef struct objc_object *id;
2、类:Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。
#import "objc/runtime.h" 查看runtime.h中 objc_class结构体实现
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE; //父类
const char * _Nonnull name OBJC2_UNAVAILABLE; //类名
long version OBJC2_UNAVAILABLE; //类的版本信息
long info OBJC2_UNAVAILABLE; //类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; //类的实例变量大小
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE; //类的实例变量列表
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE; //方法链表
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE; //方法缓存
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE; //协议链表
#endif
image
向一个Objective-C对象发送消息时,运行时库会根据实例对象的
isa
指针找到这个实例对象所属的类。Runtime库会在类的方法列表由super_class
指针找到父类的方法列表直至根类NSObject中去寻找与消息对应的selector指向的方法。找到后即运行这个方法
1、 isa:实例对象->类->元类->(`不经过父元类`)直接到根元类(NSObject的元类),`根元类的isa指向自己`;
2、 superclass:类->父类->...->根类NSObject,`元类->父元类->...->根元类->根类`,NSObject的superclass指向nil。
三、方法
一、Class
1、get 类名,父类;实例变量;属性;实例方法,类方法,方法实现;
//类名
OBJC_EXPORT const char * _Nonnull
class_getName(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//父类
OBJC_EXPORT Class _Nullable
class_getSuperclass(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//类定义的版本号
OBJC_EXPORT int
class_getVersion(Class _Nullable cls)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//类实现大小
OBJC_EXPORT size_t
class_getInstanceSize(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//类的实例变量的信息
OBJC_EXPORT Ivar _Nullable
class_getClassVariable(Class _Nullable cls, const char * _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//类的实例对象方法
OBJC_EXPORT Method _Nullable
class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//类实例对象的实例变量的信息
OBJC_EXPORT Ivar _Nullable
class_getInstanceVariable(Class _Nullable cls, const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//类方法
OBJC_EXPORT Method _Nullable
class_getClassMethod(Class _Nullable cls, SEL _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//获取的方法实现
OBJC_EXPORT IMP _Nullable
class_getMethodImplementation(Class _Nullable cls, SEL _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//获取指定的属性
OBJC_EXPORT objc_property_t _Nullable
class_getProperty(Class _Nullable cls, const char * _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//源自于类的动态库名称
OBJC_EXPORT const char * _Nullable
class_getImageName(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
2、copy 实例变量列表,方法列表,协议列表,属性列表
//实例变量列表
OBJC_EXPORT Ivar _Nonnull * _Nullable
class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//方法列表
OBJC_EXPORT Method _Nonnull * _Nullable
class_copyMethodList(Class _Nullable cls, unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//协议列表
OBJC_EXPORT Protocol * __unsafe_unretained _Nonnull * _Nullable
class_copyProtocolList(Class _Nullable cls, unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//属性列表
OBJC_EXPORT objc_property_t _Nonnull * _Nullable
class_copyPropertyList(Class _Nullable cls, unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
3、add 实例变量、属性、方法、协议
//增加方法
OBJC_EXPORT BOOL
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
const char * _Nullable types)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//增加实例变量
OBJC_EXPORT BOOL
class_addIvar(Class _Nullable cls, const char * _Nonnull name, size_t size,
uint8_t alignment, const char * _Nullable types)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//增加协议
OBJC_EXPORT BOOL
class_addProtocol(Class _Nullable cls, Protocol * _Nonnull protocol)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//增加属性
OBJC_EXPORT BOOL
class_addProperty(Class _Nullable cls, const char * _Nonnull name,
const objc_property_attribute_t * _Nullable attributes,
unsigned int attributeCount)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
4、replace 属性、方法
//替换属性
OBJC_EXPORT void
class_replaceProperty(Class _Nullable cls, const char * _Nonnull name,
const objc_property_attribute_t * _Nullable attributes,
unsigned int attributeCount)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
//替换方法
OBJC_EXPORT IMP _Nullable
class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
const char * _Nullable types)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
5、responds 方法
//类实例是否响应指定的selector,返回BOOL值
OBJC_EXPORT BOOL
class_respondsToSelector(Class _Nullable cls, SEL _Nonnull sel)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
6、conforms 协议
//判断是否实现协议,返回一个BOOL值
OBJC_EXPORT BOOL
class_conformsToProtocol(Class _Nullable cls, Protocol * _Nullable protocol)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
二、objc
1、get 类,实例变量,实例变量的值,元类,协议,关联对象,类列表
//返回指定类
OBJC_EXPORT Class _Nullable
objc_getClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//返回指定类的元类
OBJC_EXPORT Class _Nullable
objc_getMetaClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//获取已注册的类定义列表
OBJC_EXPORT int
objc_getClassList(Class _Nonnull * _Nullable buffer, int bufferCount)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//协议
OBJC_EXPORT Protocol * _Nullable
objc_getProtocol(const char * _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//关联对象
OBJC_EXPORT id _Nullable
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);
//获取对象中实例变量的值
OBJC_EXPORT id _Nullable
object_getIvar(id _Nullable obj, Ivar _Nonnull ivar)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//获取类实例的实例变量的值
OBJC_EXPORT Ivar _Nullable
object_getInstanceVariable(id _Nullable obj, const char * _Nonnull name,
void * _Nullable * _Nullable outValue)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
OBJC_ARC_UNAVAILABLE;
//返回对象的类
OBJC_EXPORT Class _Nullable
object_getClass(id _Nullable obj)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
2、copy 类列表,协议列表
//类列表
OBJC_EXPORT Class _Nonnull * _Nullable
objc_copyClassList(unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.7, 3.1, 9.0, 1.0, 2.0);
//协议列表
OBJC_EXPORT Protocol * __unsafe_unretained _Nonnull * _Nullable
objc_copyProtocolList(unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
3、set 实例变量,类,实例变量的值
//设置实例变量
OBJC_EXPORT void
object_setIvar(id _Nullable obj, Ivar _Nonnull ivar, id _Nullable value)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//设置对象中实例变量的值
OBJC_EXPORT void
object_setIvarWithStrongDefault(id _Nullable obj, Ivar _Nonnull ivar,
id _Nullable value)
OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
//改变类实例的实例变量的值
OBJC_EXPORT Ivar _Nullable
object_setInstanceVariable(id _Nullable obj, const char * _Nonnull name,
void * _Nullable value)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
OBJC_ARC_UNAVAILABLE;
//设置对象的类
OBJC_EXPORT Class _Nullable
object_setClass(id _Nullable obj, Class _Nonnull cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
4、dispose
//释放给定对象的内存
OBJC_EXPORT id _Nullable
object_dispose(id _Nullable obj)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
OBJC_ARC_UNAVAILABLE;
5、创建类、销毁类
//创建一个类或者元类
OBJC_EXPORT Class _Nullable
objc_allocateClassPair(Class _Nullable superclass, const char * _Nonnull name,
size_t extraBytes)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//销毁一个类或者元类
OBJC_EXPORT void
objc_disposeClassPair(Class _Nonnull cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
// 在应用中注册由objc_allocateClassPair创建的类
void objc_registerClassPair ( Class cls );
6、创建、销毁对象
//创建对象
OBJC_EXPORT id _Nullable
class_createInstance(Class _Nullable cls, size_t extraBytes)
OBJC_RETURNS_RETAINED
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//销毁
OBJC_EXPORT void * _Nullable objc_destructInstance(id _Nullable obj)
OBJC_AVAILABLE(10.6, 3.0, 9.0, 1.0, 2.0)
OBJC_ARC_UNAVAILABLE;
三、数据类型
struct objc_ivar {
char * _Nullable ivar_name OBJC2_UNAVAILABLE;
char * _Nullable ivar_type OBJC2_UNAVAILABLE;
int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
}
1、ivar_get
//获取实例变量名称
OBJC_EXPORT const char * _Nullable
ivar_getName(Ivar _Nonnull v)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回实例变量类型字符串
OBJC_EXPORT const char * _Nullable
ivar_getTypeEncoding(Ivar _Nonnull v)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回实例变量的偏移量
OBJC_EXPORT ptrdiff_t
ivar_getOffset(Ivar _Nonnull v)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
2、property_get
//获取属性名称
OBJC_EXPORT const char * _Nonnull
property_getName(objc_property_t _Nonnull property)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回属性的属性字符串
OBJC_EXPORT const char * _Nullable
property_getAttributes(objc_property_t _Nonnull property)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回属性的属性属性数组
OBJC_EXPORT objc_property_attribute_t * _Nullable
property_copyAttributeList(objc_property_t _Nonnull property,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
四、函数
struct objc_method {
SEL _Nonnull method_name OBJC2_UNAVAILABLE;
char * _Nullable method_types OBJC2_UNAVAILABLE;
IMP _Nonnull method_imp OBJC2_UNAVAILABLE;
}
- SEL _Nonnull method_name 选择器,表示一个方法的selector的指针,映射方法的名字
- char *method_types 方法类型
- IMP _Nonnull method_imp 方法实现
1、method_get
//获得方法名
OBJC_EXPORT SEL _Nonnull
method_getName(Method _Nonnull m)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//获得方法的实现
OBJC_EXPORT IMP _Nonnull
method_getImplementation(Method _Nonnull m)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回描述方法参数和返回类型的字符串
OBJC_EXPORT const char * _Nullable
method_getTypeEncoding(Method _Nonnull m)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回方法接受的参数个数
OBJC_EXPORT unsigned int
method_getNumberOfArguments(Method _Nonnull m)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
2、method_copy
//获取方法返回值类型字符串
OBJC_EXPORT char * _Nonnull
method_copyReturnType(Method _Nonnull m)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回方法单个参数类型的字符串
OBJC_EXPORT char * _Nullable
method_copyArgumentType(Method _Nonnull m, unsigned int index)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
3、method_set
//设置方法的实现
OBJC_EXPORT IMP _Nonnull
method_setImplementation(Method _Nonnull m, IMP _Nonnull imp)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
4、method_exchangeImplementations
//交换两个方法
OBJC_EXPORT void
method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
5、sel_
//返回指定选择器的方法名称
OBJC_EXPORT const char * _Nonnull
sel_getName(SEL _Nonnull sel)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//使用Objective-C运行时系统注册方法,映射方法 *命名为选择器,并返回选择器值。
OBJC_EXPORT SEL _Nonnull
sel_registerName(const char * _Nonnull str)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
//比较两个选择器
OBJC_EXPORT BOOL
sel_isEqual(SEL _Nonnull lhs, SEL _Nonnull rhs)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
五、协议
//判断一个协议是否符合另一个协议,返回BOOL
OBJC_EXPORT BOOL
protocol_conformsToProtocol(Protocol * _Nullable proto,
Protocol * _Nullable other)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//协议比较两个协议是否相等
OBJC_EXPORT BOOL
protocol_isEqual(Protocol * _Nullable proto, Protocol * _Nullable other)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//获取协议名称
OBJC_EXPORT const char * _Nonnull
protocol_getName(Protocol * _Nonnull proto)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//获取协议的属性
OBJC_EXPORT objc_property_t _Nullable
protocol_getProperty(Protocol * _Nonnull proto,
const char * _Nonnull name,
BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//返回协议属性列表
OBJC_EXPORT objc_property_t _Nonnull * _Nullable
protocol_copyPropertyList(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//协议采用的协议列表
OBJC_EXPORT Protocol * __unsafe_unretained _Nonnull * _Nullable
protocol_copyProtocolList(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//向协议中增加方法
OBJC_EXPORT void
protocol_addMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull name,
const char * _Nullable types,
BOOL isRequiredMethod, BOOL isInstanceMethod)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
//协议中增加属性
OBJC_EXPORT void
protocol_addProperty(Protocol * _Nonnull proto, const char * _Nonnull name,
const objc_property_attribute_t * _Nullable attributes,
unsigned int attributeCount,
BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
//指示一个协议是否遵守另一个协议。返回值BOOL
OBJC_EXPORT BOOL
protocol_conformsToProtocol(Protocol * _Nullable proto,
Protocol * _Nullable other)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
六、消息发送和消息转发
1、消息发送:方法调用称为向对象发送消息
id objc_msgSend(id self, SEL op, ...);
self:消息的接收者 op: 消息的方法名,C 字符串... :参数列表
2、消息转发
1、动态方法解析
//类
+ (BOOL)resolveClassMethod:(SEL)name;
//对象
+ (BOOL)resolveInstanceMethod:(SEL)name
//根据方法调用者类型,从其中二选一
2、备援接收者:动态方法解析没有实现或者无法处理的时候,就会执行;,如果咩有备援接收者,返回nil
- (id)forwardingTargetForSelector:(SEL)aSelector;
3、消息转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
- (void)forwardInvocation: (NSInvocation*)invocation;
具体代码实现:
在没有实现方法的前提下,去调用方法,才会触发消息转发。否则不会
[self performSelector:@selector(clickButtonHub) withObject:self afterDelay:0.3];
void dynamicAdditionMethodIMP(id self, SEL _cmd) {
NSLog(@"dynamicAdditionMethodIMP");
}
+ (BOOL)resolveInstanceMethod:(SEL)name {
NSLog(@"动态方法解析");
//判断没有实现方法, 那么我们就是动态添加一个方法
if (name == @selector(clickButtonHub)) {
class_addMethod([self class], name, (IMP)dynamicAdditionMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:name];
}
//消息备援接收者
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"消息备援接收者");
return [super forwardingTargetForSelector:aSelector];
}
//消息重新定向
- (void)forwardInvocation: (NSInvocation*)invocation{
NSLog(@"消息重新定向1");
[super forwardInvocation:invocation];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSLog(@"消息重新定向2");
return [super methodSignatureForSelector:aSelector];
}
//打印
2019-01-17 17:34:57.514365+0800 Demo[3174:1499686] 动态方法解析
2019-01-17 17:34:57.514504+0800 Demo[3174:1499686] dynamicAdditionMethodIMP
注释掉动态方法里面这段代码
/*
if (name == @selector(clickButtonHub)) {
class_addMethod([self class], name, (IMP)dynamicAdditionMethodIMP, "v@:");
return YES;
}
*/
//打印
2019-01-17 17:40:21.169707+0800 Demo[3280:1520341] 动态方法解析
2019-01-17 17:40:21.169854+0800 Demo[3280:1520341] 消息备援接收者
2019-01-17 17:40:21.170009+0800 Demo[3280:1520341] 消息重新定向2
生成方法签名转发消息
[self performSelector:@selector(clickButtonHub) withObject:self afterDelay:0.3];
+ (BOOL)resolveInstanceMethod:(SEL)name {
NSLog(@"动态方法解析");
return [super resolveInstanceMethod:name];
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"消息备援接收者");
return [super forwardingTargetForSelector:aSelector];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSLog(@"消息重新定向2");
//转化字符
NSString *sel = NSStringFromSelector(aSelector);
//判断, 手动生成签名
if([sel isEqualToString:@"clickButtonHub"]){
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}else{
return [super methodSignatureForSelector:aSelector];
}
}
//消息重新定向
- (void)forwardInvocation: (NSInvocation*)invocation{
NSLog(@"消息重新定向1");
//取得消息
SEL selector = [invocation selector];
//转发
ClassStudentModel *model = [[ClassStudentModel alloc]init];
if ([model respondsToSelector:selector]) {
//调用对象,进行转发
[invocation invokeWithTarget:model];
}else{
[super forwardInvocation:invocation];
}
}
//ClassStudentModel.h 中
@interface ClassStudentModel : NSObject
- (void)clickButtonHub;
@end
//ClassStudentModel.m
@implementation ClassStudentModel
- (void)clickButtonHub{
NSLog(@"ClassStudentModel---clickButtonHub");
}
//打印结果
2019-01-17 17:49:51.947708+0800 Demo[3564:1558162] 动态方法解析
2019-01-17 17:49:51.947831+0800 Demo[3564:1558162] 消息备援接收者
2019-01-17 17:49:51.947925+0800 Demo[3564:1558162] 消息重新定向2
2019-01-17 17:49:51.948028+0800 Demo[3564:1558162] 动态方法解析
2019-01-17 17:49:51.948115+0800 Demo[3564:1558162] 消息重新定向1
2019-01-17 17:49:51.948211+0800 Demo[3564:1558162] ClassStudentModel---clickButtonHub
@end
网友评论