Selector 常见用法

定义

  • 1.Selector就是用字符串表示某个对象的某个method.
  • 更专业的说法就是:OC的virtual table中指向实际执行function pointer的一个C字串
    Selector有什么用途?
    因为method可以用字符串表示,因此,某个method就可以变成用来传递的参数

Objective-C的对象会被编译成Structure

@interface MyClass : NSObject {
    int a;
}
@end

会被编译成

typedef struct {
    int a;
} MyClass;

对Class加入method

在执行的时候,runtime会为每个class做好一张表格(virtual table),表格里面会以一个字符串当key,每个key会对应到C function的指针位置。runtime里面,把实现的C function定义成IMP类型,拿来当做key的字符串,就叫做selector,定义为SEL类型,然后我们就可以使用@selector关键字建立selector。

image.png

注意:
在OC中一个class会有哪些method并不是固定的,如果我们在对某个对象调用了不存在的method的时候,编译的时候,compiler不会出错,只会警告,知道实际执行的时候才会产生unrecognized selector sent to instance的错误导致应用crash,之所以只有警告,而不是错误,是因为method可能之后才会加入。
由于在oc中,对象有哪些method可以在runtime改变,所以我称之为动态语言。
我们可以通过category实现,也可以手动将某个method加入到某个class中。
定义一个C function,至少要有两个参数,一个是执行method的物体,第二个是selector,如下:

void myMethodIMP(id self, SEL _cmd)
{
    doSomething();
}

然后调用class_addMethod加入

class_addMethod([MyClass class], @selector(myMethod), (IMP)myMethodIMP, "v@:");
image.png

Selector有什么用途?

1.Target/Action pattern

检验某个对象是否实现了某个方法:
调用respondsToSelector:<#(SEL)#>就可以了
也可以使用:

 @try {
        <#Code that can potentially throw an exception#>
    } @catch (NSException *exception) {
        <#Handle an exception thrown in the @try block#>
    } @finally {
        <#Code that gets executed whether or not an exception is thrown#>
    }

在OC中并不鼓励使用,大量使用会导致内存泄露(Memory Leak),由于传统的OC内存管理使用auto-release的机制,半自动释放——将一些应该要释放的对象延迟释放,在这一轮runloop中先不释放,而是到下一个runloop开始时才释放这些内存。如果使用try-catch捕捉意外错误,就会跳出原本的runloop,而导致应该释放的内存没有释放,造成内存泄露。

2、Timer

延迟执行某个方法:
[self performSelector:@selector(doSomething) withObject:nil afterDelay:1.0];
在时间没到的时候,可以取消:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doSomething) object:nil];
timer语法使用:

 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doSomething) userInfo:nil repeats:YES];

通过建立NSInvocation对象建立timer

NSMethodSignature *sign = [MyClass instanceMethodSignatureForSelector:@selector(doSomething)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sign];
[invocation setTarget:someObject];
[invocation setSelector:@selector(doSomething)];
[invocation setArgument:&anArgument atIndex:2];
[NSTimer scheduledTimerWithTimeInterval:1.0 invocation:invocation repeats:YES];

注意:
在设置参数的时候setArgument: atIndex:参数要从2开始,因为0的位置是self,1的位置是selector。

3、接收NSNotification

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething) name:@"notiName" object:nil];

4.在某个线程执行method

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;

假如一件事执行太久,可以丢到后台线程中,就是另外建立一条Thread执行:
[self performSelectorInBackground:@selector(doSomething) withObject:nil];
注意:在后台线程执行需要建立自己的autoreleasepool,执行完之后通知主线程。

5.Array排序

NSArray *sortedArray = [anArray sortedArrayUsingSelector:@selector(localizedCompare:)];
我们也可以通过传递selector,要求Array里面每一个对象都执行一次指定的method。
[anArray makeObjectsPerformSelector:@selector(doSomething)];

6、对super调用PerformSelector:

[super doSomthing]
代表的是调用super的doSomething实现方法;
但如果是[super PerformSelector:@selector(doSomething)]
最终结果等同于[self doSomething];

你可能感兴趣的:(Selector 常见用法)