IMP

IMP定义在runtime的objc.h中,定义如下:

/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

typedef说明
形式:typedef 返回类型(新类型)(参数表)
typedef void (
IMP)(void /
id, SEL, ... */ ); // 定义一个名为IMP的函数指针

IMP是指向方法实现的函数指针,第一个参数是指向self的指针,第二个参数是方法选择器(SEL)。

IMP、SEL、Method

Method声明在objc-private.h中

typedef struct method_t *Method;

Method定义在objc-runtime.h文件中,定义如下:

struct method_t {
    SEL name;
    const char *types;
    IMP imp;

    struct SortBySELAddress :
        public std::binary_function<const method_t&,
                                    const method_t&, bool>
    {
        bool operator() (const method_t& lhs,
                         const method_t& rhs)
        { return lhs.name < rhs.name; }
    };
};

Method是方法的结构体,SEL和IMP是Method的成员变量,SEL表示方法选择器(@selector)的隐含类型,IMP是指向方法的实现的指针。

方法选择器用于表示方法运行时的名称。方法选择器是个C字符串,在运行时注册(或 “mapped”)。当类加载时(load),编译器生成的方法选择器在运行时自动映射到类。

image.png

IMP的简单使用

注意:修改Enable Strict Checking of objc_msgSend Calls为NO,不强制检查IMP类型。

模拟网络请求回调,创建AViewModel,定义- (void)requestData:(NSString *)cls方法,通过类名和方法名获取指向方法实现的指针(IMP),调用IMP传值给AViewController。

AViewController

- (IBAction)buttonClick:(UIButton *)sender {
    AViewModel *viewmodel = [[AViewModel alloc]init];
    [viewmodel requestData: NSStringFromClass(self.class)];
}

- (void)responseData: (NSString *)result {
    NSLog(@"%s --- %@", __func__, result);
}

AViewModel

- (void)requestData:(NSString *)cls {
    Class class = NSClassFromString(cls);

    SEL sel = NSSelectorFromString(@"responseData:");
    Method method = class_getInstanceMethod(class, sel);
    IMP imp = method_getImplementation(method);
    imp(class, sel, @"s");
}

使用IMP的好处:解耦,AViewModel调用AViewController的方法,不需要知道AViewController
缺点:字符串的方式接受类名和方法名,没有编译期的检查,方法名写错会造成运行时崩溃。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容