美文网首页iOS底层
OC中一些方法的调用情况

OC中一些方法的调用情况

作者: Sweet丶 | 来源:发表于2020-10-24 16:52 被阅读0次
一. class方法

class方法的源码

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

+ (Class)superclass {
    return self->superclass;
}

- (Class)superclass {
    return [self class]->superclass;
}

由上可知:

  1. 调用对象方法[self class]和[super class]最终都是返回的是自身的类对象。[super class]调用时是从父类方法列表中开始寻找class方法再进行调用,最终会来到NSObject类里的class方法,所以结果是一致的。
  2. 类方法的class最终返回的都是自身。
  3. 获取superclass时,不管是对象方法还是类方法,返回的都是父类。
二. isMemberOfClass和isKindOfClass方法

isMemberOfClass方法的源码

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

由上可知:

  1. 调用对象方法isMemberOfClass时,比对的是类对象是否相同。
  2. 调用类方法isMemberOfClass时,比对的是元类对象是否与参数相同。
  3. 调用对象方法isKindOfClass时,判断的是自身类对象是否与参数class或者其父类相同。
  4. 调用类方法isKindOfClass时,判断的是元类对象是否与参数及其父类相同。
三. 子线程调用 - (void)performSelector: withObject:afterDelay:;

在开启的子线程调用延时performSelector方法,实际并未调用的情况如下:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
    [self performSelector:@selector(test1:) withObject:@"test1" afterDelay:0.5];
    [self performSelector:@selector(test2:) withObject:@"test2" afterDelay:0.5 inModes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]];
});

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

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

在开启的子线程中使用方法- (void)performSelector: withObject:afterDelay:, Selector并没有执行,经过查看GUNStep源码

- (void) performSelector: (SEL)aSelector
          withObject: (id)argument
          afterDelay: (NSTimeInterval)seconds
{
  NSRunLoop     *loop = [NSRunLoop currentRunLoop];
  GSTimedPerformer  *item;

  item = [[GSTimedPerformer alloc] initWithSelector: aSelector
                         target: self
                       argument: argument
                          delay: seconds];
  [[loop _timedPerformers] addObject: item];
  RELEASE(item);
  [loop addTimer: item->timer forMode: NSDefaultRunLoopMode];
}

由上可知,该方法的本质是创建了一个timer, 然后将timer添加到currentRunLoop中,再由timer触发aSelector调用,所以出现问题的原因就出来了:

  1. 在子线程中,runloop是未开启的,开启runloop需要创建runloop并调用runloop 的开启方法。
// 创建的方式
NSRunLoop       *loop = [NSRunLoop currentRunLoop];
// 开启runloop的方式:首先要添加inputsource或者timer,不然运行了也会立即退出

// 开启永久的runloop,无法被停止。
- (void)run; 
//开启直到limitDate的runloop,期间无法被停止。 
- (void)runUntilDate:(NSDate *)limitDate;
// 开启一次runloop。
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;

// 一般开启一个可控的runloop,方式为:控制shouldKeepRunning变量
BOOL shouldKeepRunning = YES; // global
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
  1. 方法- (void)performSelector: withObject:afterDelay:中创建的timer添加到了当前的runloop中,但是runloop未开启,所以计时器未开启,所以方法得不到触发调用。

  2. 要让这个方法得到触发执行,有两种方式:
    -》到主线程中调用。
    -》在子线程中调用,需要手动去开启线程的runloop,开启的方法在1中。

  3. 延时任务也可用其它方法来实现,比如dispatch_after

相关文章

  • iOS原生&JS交互

    OC 获取js中的key OC调用js方法 JS调用OC中不带参数的block JS调用OC中带参数的block ...

  • OC 和 swift 混编遇到的坑

    swift 中定义的方法不被翻译 如果你在 OC 类中调用 swift 类中自定义的方法,遇到无法调用的情况。 这...

  • 3,消息转发机制

    1,OC方法的调用 OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用...

  • objc_msgSend调用流程

    oc的方法调用 OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用者)...

  • OC和JS的交互那点事

    1、OC调用JS代码 在代理方法webViewDidFinishLoad:方法中调用JS代码 2、JS调用OC代码...

  • quick cocos Lua与OC互相回调,苹果内购机制

    1.在需要调用oc中的lua方法中写入调用oc的接口方法,把参数传递进去给oc层使用 2.在对应oc中的方法中拿到...

  • OC和Swift混编遇到的一些小麻烦

    一. OC中调用swift类中的方法时,编译器有时找不到方法声明 OC调用swift类中的方法,swift类需要有...

  • Runtime的原理

    OC的消息机制 OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver方法调用者 发...

  • 从OC到Swift

    Swift调用OC类和方法 在工程名-Bridging-Header.h中添加需要调用OC类的头文件.h OC调用...

  • WebViewJavascriptBridge 使用

    目的 掌握 OC 调用 JS方法 JS 调用 OC方法 OC——>sender JS——> sender OC 调...

网友评论

    本文标题:OC中一些方法的调用情况

    本文链接:https://www.haomeiwen.com/subject/xjwimktx.html