读书笔记Objective-CiOS 杂谈

(2018年3月22号重编)kkbox-ios-dev笔记(一)

2017-02-13  本文已影响203人  百草纪

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];
  • 注意:在调用NSInvocationsetArgument: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...elseswitch...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,反过来,也可以使用NSSelectorFromStringNSString转成selector

调用PrivateAPI

  • OC 没有真正所谓私有的方法,一个对象实现了哪些方法,即使没有 import头文件,我们都可以调用。可以通过performSelector:调用。但苹果不推荐,App Store上也会拒绝。

注意点:super调用performSelector:的区别

[super doSomthing];//代表的是调用父类的方法实现

[super performSelector:@selector(doSomething)] 
// 调用父类的 performSelector ,结果等同于 [self doSomething]

Refactor工具

  • 在要修改名字上面点击鼠标右键,选择Refactor中的Rename
  • 如果是通过performSelector:调用执行的方法,并不会把里面的 selector也换掉,只是会出现警告。

selectorOC所有魔法的开始

上一篇下一篇

猜你喜欢

热点阅读