Runtime 方法 (一)

總結:
Class

get 類名,父類;實例變量;屬性;實例方法,類方法,方法實現;

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。