- (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的方法都可以使用類方法直接調用
我們先看下面代碼漫贞,首先實現(xiàn)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: 執(zhí)行");
}
@end
@implementation NSString (myTest)
- (void)testFunc
{
NSLog(@"NSString testFunc: 執(zhí)行");
}
- (void)testString {
NSLog(@"NSString testString: 執(zhí)行");
}
@end
在ViewController中分別使用類調用分類中的方法:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[NSObject testFunc];
[NSString testFunc];
[NSString testString];
}
@end
問題:
1.首先是否能成功編譯
2.如果能成功編譯執(zhí)行結果是什么九杂,為什么會出現(xiàn)這個結果呢
回答:
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: 執(zhí)行
2018-05-03 15:58:22.668791+0800 test--OC-ObjectModel[12480:498039] NSObject testFunc: 執(zhí)行
NSString和NSObject調用testFunc方法執(zhí)行結果一樣,最后都是執(zhí)行NSObject分類的testFunc方法攘蔽。
3.分析原因:
NSObject實例方法是特殊的,可以使用類來調用政模,這個特殊性也是由于OC對象模型決定的岗宣,類對象模型里主要包括實例對象-》類對象-》類元對象, 1)實例方法調用會從類對象開始搜索方法淋样,如果在類對象里沒有搜索到方法耗式,則沿父類對象網(wǎng)上搜索,直到NSObject這個類對象為止趁猴, 2)類方法調用會從元類對象開始搜索方法刊咳,如果在元類對象里沒有搜索到方法,則沿父元類對象網(wǎng)上搜索儡司,到NSObject這個元類對象還是沒有搜索到娱挨,則會搜索NSObject這個元類對象的父對象NSObject類對象。
所以捕犬,上面兩個類方法調用都沿著元類對象一直找到的NSObject這個類對象跷坝。
嘗試:依據(jù)方法搜索原理,如果使用實例調用類方法會報錯的碉碉,大伙可以自己試驗下柴钻。
參考文章:iOS 方法調用的過程