2018年3月22号重编,复习,补充,完善。
2017年5月31号重编,简写。
Selector
Selector
就是用字符串表示某个对象的某个方法Objective-C
Class/Object
到底是什么?
Objective-C
程序在编译运行时,会编译成C
语言。Objective-C
类会编译成C
的结构体,方法和block
会被编译成C
方法,- 在执行的时候,运行时会创建与
C
结构体和C
方法的关联。对类加入方法
- 在执行的时候,
Runtime
会为每个类准备好一张表格,表格里面会以一个字符串key
(又称:selector
)对应到C
方法的指定位置。把实现的 C 方法定义成IMP
这个类型(又称:SEL
,SEL
就是C
字串)。- 对一个对象调用某个方法,
Runtime
就把方法的名称当作字符串,寻找与字符串合适的C
方法的实现,然后执行。// 1: 这三种调用是一样的 [myObject doSomthing]; //2 [myObject performSelector:@selector(doSomething)]; //3 objc_msgSend(myObject, @selector(doSomething), NULL);
要求某个对象执行某个方法
=要求某个对象执行某个 selector
- 一个类有哪些方法,是在
Runtime
一个一个加入的,所以就有机会在程序正在执行时,继续对某个类操作。- 在
OC
中,一个类会有哪些方法,并不是固定的。- 如果不想用分类,而想要手动将某个方法加入到某个类,至少有两个参数,一个是执行的对象,一个是
selector
// 目前不适应,仅供参考 //1 定义 C 方法 void myMethodIMP(id self, SEL _cmd) { doSomething(); } //2 加入 selector 与对象的关系 class_addMethod([MyClass class], @selector(myMethod), (IMP)myMethodIMP, "v@:"); // 3. 调用 MyClass *myObject = [[MyClass alloc] init]; [myObject myMethod];
Selector用途
Selector
主要用途就是实现target
(谁调用?)/action
(执行什么方法)// 1. 定义 @interface MyButton : NSView { id target; SEL action; } @property (assign) IBOutlet id target; @property (assign) SEL action; @end @implementation MyButton - (void)mouseDown:(NSEvent *)e { [super mouseDown:e]; [target performSelector:action withObject:self]; } @synthesize target, action; @end // 2.使用 [(MyButton *)button setTarget:self]; [(MyButton *)button setAction:@selector(clickAction:)];
检查方法是否存在
respondsToSelector:
BOOL scale = 1.0; if ([[UIScreen mainScreen] >respondsToSelector:@selector(scale)]) { scale = [UIScreen mainScreen].scale; }
Timer
// 1. 多久后执行 [self performSelector:@selector(doSomething) withObject:nil afte rDelay:1.0]; // 2. 取消刚才执行的方法 [NSObject cancelPreviousPerformRequestsWithTarget:self];
NSInvocation
其实就是将target/action
以及这个action
中要传递给target
的参数这三者,在包装成一个对象。NSMethodSignature *sig = [MyClass >instanceMethodSignatureForSele ctor:@selector(doSomething:)]; NSInvocation *invocation = [NSInvocation >invocationWithMethodSig nature:sig]; [invocation setTarget:someObject]; [invocation setSelector:@selector(doSomething:)]; [invocation setArgument:&anArgument atIndex:2]; NSTimer *timer = [NSTimer >scheduledTimerWithTimeInterval:1.0 invocation:invocation repeats:YES];
- 注意:在调用
NSInvocation
的setArgument:atIndex:
方法时,要传递的参数至少要从 2 开始,由于是给objc_msgSend
调用用的参数,在 0 的参数是对象自己,位置 1 的则是selector
.在某个线程执行方法
-performSelectorOnMainThread:withObject:waitUntilDone:modes:
-performSelectorOnMainThread:withObject:waitUntilDone:
-performSelector:onThread:withObject:waitUntilDone:modes:
-performSelector:onThread:withObject:waitUntilDone:
-performSelectorInBackground:withObject:
- 在子线程执行完任务后,可以通过
-performSelectorOnMainThread:withObject:waitUntilDone:
通知主线程执行完毕。Array排序
- 如果一个数组里面都是字符串的话,我们就可以使用
compare:
排序。NSString
的方法localizedCompare
,会参考系统语言决定排序方式,比如:简体中文下用拼音排序,繁体中文下用笔画排序等等。- 可变数组用的:
sortUsingSelector
- 不可变数组用的:
sortedArrayUsingSelector
,会产生新的数组。NSArray *sortedArray = [anArray sortedArrayUsingSelector: @selector(localizedCompare:)];
- 要求数组中的所有对象执行某个方法:
makeObjectsPerformSelector:
代替
if...else
与switch...case
[super viewDidLoad]; person * onject = [[person alloc]init]; int condition = 0; switch(condition) { case 0: [onject run]; break; case 1: [onject doSomeThing]; break; default: break; }
- 代替方法:
[onject performSelector:NSSelectorFromString(@[@"run",@"doSomeThing"][condition])];
- 我们可以使用
NSStringFromSelector
,将selector
转换成NSString
,反过来,也可以使用NSSelectorFromString
将NSString
转成selector
。调用
Private
API
- OC 没有真正所谓私有的方法,一个对象实现了哪些方法,即使没有
import
头文件,我们都可以调用。可以通过performSelector:
调用。但苹果不推荐,App Store
上也会拒绝。注意点:用
super
调用performSelector:
的区别[super doSomthing];//代表的是调用父类的方法实现 [super performSelector:@selector(doSomething)] // 调用父类的 performSelector ,结果等同于 [self doSomething]
Refactor工具
- 在要修改名字上面点击鼠标右键,选择
Refactor
中的Rename
。- 如果是通过
performSelector:
调用执行的方法,并不会把里面的selector
也换掉,只是会出现警告。
selector
是OC
所有魔法的开始
网友评论