美文网首页
关于- (void)performSelector:(SEL)a

关于- (void)performSelector:(SEL)a

作者: hello_iOS程序媛 | 来源:发表于2018-05-03 16:34 被阅读0次

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay是NSObject分类中的方法:

// 位于NSRunLoop.h头文件中
@interface NSObject (NSDelayedPerforming)  

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullable id)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

@end

某次用类如ViewController直接调用- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay方法,运行成功:

[ViewController performSelector:@selector(test:) withObject:@"abc" afterDelay:0.5];

运行成功原因:NSObject的方法都可以使用类方法直接调用

OC对象模型

我们先看下面代码,首先实现NSObject和NSString的两个分类:

#import <Foundation/Foundation.h>
@interface NSObject (myTest)
- (void)testFunc;
@end

@interface NSString (myTest)
- (void)testFunc;
- (void)testString;
@end

@implementation NSObject (myTest)
-(void) testFunc
{
    NSLog(@"NSObject testFunc: 执行");
}
@end

@implementation NSString (myTest)
- (void)testFunc
{
    NSLog(@"NSString testFunc: 执行");
}

- (void)testString {
    NSLog(@"NSString testString: 执行");
}
@end

在ViewController中分别使用类调用分类中的方法:

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [NSObject testFunc];
    [NSString testFunc];
    [NSString testString];
}
@end

问题:
1.首先是否能成功编译
2.如果能成功编译执行结果是什么,为什么会出现这个结果呢

回答:
1.不能成功编译, [NSString testString]会报如下错误

No known class method for selector 'testString'

从错误原因可以明显看到 NSString没有testString类方法。

对编译不成功的代码删除后如下重新编译,成功运行

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    [NSObject testFunc];
    [NSString testFunc];
}
@end

2.运行结果:

2018-05-03 15:58:22.668416+0800 test--OC-ObjectModel[12480:498039] NSObject testFunc: 执行
2018-05-03 15:58:22.668791+0800 test--OC-ObjectModel[12480:498039] NSObject testFunc: 执行

NSString和NSObject调用testFunc方法执行结果一样,最后都是执行NSObject分类的testFunc方法。

3.分析原因:
NSObject实例方法是特殊的,可以使用类来调用,这个特殊性也是由于OC对象模型决定的,类对象模型里主要包括实例对象-》类对象-》类元对象, 1)实例方法调用会从类对象开始搜索方法,如果在类对象里没有搜索到方法,则沿父类对象网上搜索,直到NSObject这个类对象为止, 2)类方法调用会从元类对象开始搜索方法,如果在元类对象里没有搜索到方法,则沿父元类对象网上搜索,到NSObject这个元类对象还是没有搜索到,则会搜索NSObject这个元类对象的父对象NSObject类对象。
所以,上面两个类方法调用都沿着元类对象一直找到的NSObject这个类对象。

尝试:依据方法搜索原理,如果使用实例调用类方法会报错的,大伙可以自己试验下。

参考文章:iOS 方法调用的过程

performSelector的原理以及用法

相关文章

网友评论

      本文标题:关于- (void)performSelector:(SEL)a

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