SEL与IMP
#import "ViewController.h"
#import <objc/message.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//objc调用
void (^objcBlock)(NSString *) = ^(NSString *abc){
NSLog(@"objc:%@",abc);
};
((void *(*)(id, SEL,id))(void *)objc_msgSend)(objc_getClass("ViewController"), sel_registerName("test:"),@"objc");
((void *(*)(id, SEL,id,id))(void *)objc_msgSend)(self, sel_registerName("test:callBack:"),@"objc",objcBlock);
//通过sel调用
SEL sel =@selector(test:callBack:);
// SEL sel = NSSelectorFromString(@"test:callBack:");
void (^selBlock)(NSString *) = ^(NSString *abc){
NSLog(@"sel:%@",abc);
};
[self performSelector:@selector(test:callBack:) withObject:@"sel" withObject:selBlock];
//执行imp
IMP imp = [self methodForSelector:sel];
void (*func)(id, SEL,id,id) = (void *)imp;
// void (*func)(id, SEL,id,id) = (void (*)(id,SEL,id,id))imp;
func(self,@selector(test:callBack:),@"imp",^(NSString *abc){
NSLog(@"imp:%@",abc);
});
}
+ (void)test:(NSString *)test
{
NSLog(@"%@",test);
}
-(void)test:(NSString *)test callBack:(void (^)(NSString *abc))callback
{
NSLog(@"%@",test);
if (callback) {
callback(@"123");
}
}
@end
-
SEL: 类成员方法的指针,可以理解 @selector()就是取类方法的编号
通过方法名获取SEL:
SEL sel =@selector(test:); SEL sel = NSSelectorFromString(@"test:");
通过SEL获取方法名Str:
NSString *methodStr = NSStringFromSelector(@selector(test:));
根据SEL来调用方法:
[self performSelector: @selector(test:) withObject:nil];
-
IMP: 函数的指针
通过SEL获得IMPIMP imp = [Obj methodForSelector: @selector(test:)];
执行IMP
void (*func)(id, SEL, id) = (void *)imp; func(self, @selector(test:),@"123");
-
IMP和SEL关系:
SEL-IMP.png
每一个继承于NSObject的类都能自动获得runtime的支持。在这样的一个类中,有一个isa指针,指向该类定义的数据结构体,这个结构体是由编译器编译时为类(需继承于NSObject)创建的.在这个结构体中有包括了指向其父类类定义的指针以及 Dispatch table. Dispatch table是一张SEL和IMP的对应表。也就是说方法编号SEL最后还是要通过Dispatch table表寻找到对应的IMP,IMP就是一个函数指针,然后执行这个方法。
在OC种中,SEL和IMP之间的关系,好像是一个书本的”目录“,SEL是方法编号,就像”标题“一样,IMP是方法实现的真实地址,就像”页码“一样,他们是一一对应的关系。
关于SEL文章:
https://blog.csdn.net/fengsh998/article/details/8614486
iOS方法与函数
-
方法:
1,在@interface和@end之间声明,在@implementation和@end之间实现,类方法以+号开头;对象方法以-号开头#import "ViewController.h" @interface ViewController () + (void) test1; - (void) test2; @end @implementation ViewController + (void) test1 { NSLog(@"test1"); } - (void) test2 { NSLog(@"test2"); } - (void)viewDidLoad { [super viewDidLoad]; [ViewController test1]; [self test2]; } @end
2,类方法由类来调用;对象方法由对象来调用
3,方法归类、对象所有 -
函数:
1,函数能写在文件中的任意位置(@interface和@end之间除外)void test3() { NSLog(@"test3"); }
2,函数调用不依赖于对象
test3();
3,函数归文件所有。
C函数调用OC方法
https://blog.csdn.net/u010858147/article/details/52571939
网友评论