IOS开发知识点

RunTime/RunLoop

2020-10-15  本文已影响0人  Li_Po

Runtime

runtime源码地址
https://opensource.apple.com/source/objc4/
runloop源码地址
https://opensource.apple.com/tarballs/CF/

所有对象都是ID类型,对应runtime就是objc_object,结构体构成


image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

[self class]和[super class]都是调用当前对象

image.png
image.png
image.png
image.png
  • 消息转发


    image.png
#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
void testImp (void)
{
NSLog(@"test invoke");
}
//动态方法解析 添加方法 第一次机会 lp
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// 如果是test方法 打印日志
if (sel == @selector(test)) {
    NSLog(@"resolveInstanceMethod:");
    // 动态添加test方法的实现
    class_addMethod(self, @selector(test), testImp, "v@:");
    return YES;
}
else{
    // 返回父类的默认调用
    return [super resolveInstanceMethod:sel];
}
}
//动态方法解析 转发消息 第二次机会 lp
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if (aSelector == @selector(test)) {
    NSLog(@"forwardingTargetForSelector:");
    return nil;
}
return [super forwardingTargetForSelector:aSelector];
}
//方法签名 lp
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if (aSelector == @selector(test)) {
    NSLog(@"methodSignatureForSelector:");
    //返回方法签名
    // v 代表返回值是void类型的  @代表第一个参数类型是id,即      self
    // : 代表第二个参数是SEL类型的  即@selector(test)
    return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
else{
    return [super methodSignatureForSelector:aSelector];
}
}
//消息转发
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSLog(@"forwardInvocation:");
}

方法交换


image.png
image.png

Method m1 = class_getClassMethod([NSURL class], @selector(URLWithString:));
Method m2 = class_getClassMethod([NSURL class], @selector(LP_URLWithString:));
method_exchangeImplementations(m1, m2);

image.png

RunLoop

image.png
image.png
image.png
image.png
#import "ViewController.h"
typedef void (^runloopBlock)(void);

@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>

@property (nonatomic,strong)UITableView *tableView;
@property (nonatomic,strong)NSMutableArray *taskArray;
@property (nonatomic,assign)NSUInteger maxTaskCount;
@property (nonatomic,strong)NSTimer * timer;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];    
//rujnloop 的使用

//创建定时任务
CADisplayLink * play = [CADisplayLink displayLinkWithTarget:self selector:@selector(doSomeThing)];
[play addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

//_timer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(doSomeThing) userInfo:nil repeats:YES];

_taskArray = [NSMutableArray array];
_maxTaskCount = 20;

//添加runloop观察者
[self addRunloopObserver];

[self.view addSubview:self.tableView];
}

-(UITableView *)tableView{
if (!_tableView) {
    _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height) style:UITableViewStylePlain];
    _tableView.delegate = self;
    _tableView.dataSource = self;
}
return _tableView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * cellStr = @"cell";
TableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellStr];
if (!cell) {
    cell = [[TableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellStr];
}
cell.myLable.text = [NSString stringWithFormat:@"显示第%ld张图片",indexPath.row];
[self addtask:^{
    cell.myImageView1.image = [UIImage imageNamed:@"timg.jpg"];
}];
[self addtask:^{
    cell.myImageView2.image = [UIImage imageNamed:@"timg.jpg"];
}];
[self addtask:^{
    cell.myImageView3.image = [UIImage imageNamed:@"timg.jpg"];
}];
[self addtask:^{
    cell.myImageView4.image = [UIImage imageNamed:@"timg.jpg"];
}];
[self addtask:^{
    cell.myImageView5.image = [UIImage imageNamed:@"timg.jpg"];
}];


return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
}

#pragma mark runloop-- c语言代码
-(void)doSomeThing{
//z不做事情 只是让runloop一直运行
}
-(void)addtask:(runloopBlock)task{
//添加任务
[_taskArray addObject:task];
if (_taskArray.count>_maxTaskCount) {
    [_taskArray removeObjectAtIndex:0];
  }
}
static void callBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
//取出任务执行

ViewController * vc = (__bridge ViewController *)info;
if (vc.taskArray.count==0) {
    return;
}
runloopBlock block = [vc.taskArray firstObject];
if (block) {
    block();
}
[vc.taskArray removeObjectAtIndex:0];

}

-(void)addRunloopObserver{

//拿到当前的runloop
CFRunLoopRef runloop = CFRunLoopGetCurrent();

//定义上下文
CFRunLoopObserverContext context = {
    0,
    (__bridge void *)(self),
    &CFRetain,
    &CFRelease,
    NULL
};
//定义一个观察车
static CFRunLoopObserverRef  defaultModeObserver;
//创建一个观察者
defaultModeObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopAfterWaiting, YES, 0, &callBack, &context);

CFRunLoopAddObserver(runloop, defaultModeObserver, kCFRunLoopCommonModes);

CFRelease(defaultModeObserver);
 }

@end
@implementation MCObject

static NSThread *thread = nil;
// 标记是否要继续事件循环
static BOOL runAlways = YES;

+ (NSThread *)threadForDispatch{
    if (thread == nil) {
        @synchronized(self) {
            if (thread == nil) {
                // 线程的创建
                thread = [[NSThread alloc] initWithTarget:self selector:@selector(runRequest) object:nil];
                [thread setName:@"com.imooc.thread"];
                //启动
                [thread start];
            }
        }
    }
    return thread;
}

+ (void)runRequest
{
    // 创建一个Source
    CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    
    // 创建RunLoop,同时向RunLoop的DefaultMode下面添加Source
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    
    // 如果可以运行
    while (runAlways) {
        @autoreleasepool {
            // 令当前RunLoop运行在DefaultMode下面
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, true);
        }
    }
    
    // 某一时机 静态变量runAlways = NO时 可以保证跳出RunLoop,线程退出
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}
上一篇下一篇

猜你喜欢

热点阅读