- (void)run; // 默认模式
- (void)runUntilDate:(NSDate *)limitDate;
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;
第一种会一直运行下去,并且一直在NSDefaultRunLoopMode模式下,重复调用runMode:beforeDate:方法。
第二种会在超时时间之前一直在NSDefaultRunLoopMode模式下调用runMode:beforeDate:方法。
第三种则会在超时时间到达或者第一个inputsource被处理前一直调用runMode:beforeDate:方法。
可以通过NSRunLoop的分类查看
- (void)viewDidLoad {
[super viewDidLoad];
_thread = [[NSThread alloc] initWithTarget:self selector:@selector(createRunLoopInNewThread) object:nil];
[_thread setName:@"RunLoopDemo"];
[_thread start];
}
- (void)createRunLoopInNewThread {
_theRL = [NSRunLoop currentRunLoop];
_port = (NSMachPort *)[NSMachPort port];
// 添加一个端口作为输入源
[_theRL addPort:_port forMode:NSDefaultRunLoopMode];
[_theRL run];
}
NSRunLoop+Hook.h
#import <Foundation/Foundation.h>
@interface NSRunLoop (Hook)
@end
NSRunLoop+Hook.m
#import "NSRunLoop+Hook.h"
#import <objc/runtime.h>
@implementation NSRunLoop (Hook)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self _swizzleImpWithOrigin:@selector(runMode:beforeDate:) swizzle:@selector(xd_runMode:beforeDate:)];
});
}
+ (void)_swizzleImpWithOrigin:(SEL)originSelector swizzle:(SEL)swizzleSelector {
Class _class = [self class];
Method originMethod = class_getInstanceMethod(_class, originSelector);
Method swizzleMethod = class_getInstanceMethod(_class, swizzleSelector);
IMP originIMP = method_getImplementation(originMethod);
IMP swizzleIMP = method_getImplementation(swizzleMethod);
BOOL add = class_addMethod(_class, originSelector, swizzleIMP, method_getTypeEncoding(swizzleMethod));
if (add) {
class_addMethod(_class, swizzleSelector, originIMP, method_getTypeEncoding(originMethod));
} else {
method_exchangeImplementations(originMethod, swizzleMethod);
}
}
- (BOOL)xd_runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate {
NSThread *thread = [NSThread currentThread];
// 这里我们只对自己创建的线程runloop的`runMode:beforeDate:`方法进行修改.
if ([thread.name isEqualToString:@"RunLoopDemo"]) {
NSLog(@"RunLoopDemo线程 ");
return YES; //如果这里返回`NO`, runloop会立刻退出, 故要返回`YES`进行验证.
}
NSLog(@"runloop+hook: 其他可能未知的线程%@ ", thread.name);
return [self xd_runMode:mode beforeDate:limitDate];
}
@end