什么是RunLoop运行循环一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(调用run方法)RunLoop只能选择一个Mode启动,如果当前Mode中没有任何Source(Sources0、Sources1)、Timer,那么就直接退出RunLoopRunLoop作用
保持程序的持续运行处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)节省CPU资源,提高程序性能:该做事时做事,该休息时休息 ......模拟RunLoop内部实现
其实它内部就是do-while循环,在这个循环内部不断地处理各种任务(比如Source、Timer、Observer)voidmessage(intnum)
{PRintf("执行第%i个任务", num);
}intmain(intargc,constchar*argv[]) {do{
printf("有事吗? 没事我睡了");intnumber;
scanf("%i", &number);
message(number);
}while(1);return0;
}
获得RunLoop对象
RunLoop对象NSRunLoopCFRunLoopRefFoundation[NSRunLoop currentRunLoop];// 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop];// 获得主线程的RunLoop对象
Core FoundationCFRunLoopGetCurrent();// 获得当前线程的RunLoop对象
CFRunLoopGetMain();// 获得主线程的RunLoop对象
RunLoop结构
CFRunLoopRef对应RunLoop对象CFRunLoopModeRef代表RunLoop的运行模式, 系统默认注册了5个ModeNSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响NSRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的ModeCFRunLoopTimerRef是基于时间的触发器CFRunLoopTimerRef基本上说的就是NSTimer,它受RunLoop的Mode影响CFRunLoopSourceRef是事件源(输入源)CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变//1.创建Observer//第一个参数:用于分配该observer对象的内存//第二个参数:用以设置该observer所要关注的的事件//第三个参数:用于标识该observer是在第一次进入run loop时执行, 还是每次进入run loop处理时均执行//第四个参数:用于设置该observer的优先级//第五个参数: observer监听到事件时的回调blockCFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES,0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {switch(activity)
{casekCFRunLoopEntry:
NSLog(@"即将进入loop");
break;casekCFRunLoopBeforeTimers:
NSLog(@"即将处理timers");
break;casekCFRunLoopBeforeSources:
NSLog(@"即将处理sources");
break;casekCFRunLoopBeforeWaiting:
NSLog(@"即将进入休眠");
break;casekCFRunLoopAfterWaiting:
NSLog(@"刚从休眠中唤醒");
break;casekCFRunLoopExit:
NSLog(@"即将退出loop");
break;default:
break;
}
});//2.添加监听/*第一个参数: 给哪个RunLoop添加监听
第二个参数: 需要添加的Observer对象
第三个参数: 在哪种模式下监听*/CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);//3,释放observerCFRelease(observer);
RunLoopRunLoop处理逻辑RunLoopRunLoop应用NSTimer只能在指定的model下运行NSTimer *timer = [NSTimer timerWithTimeInterval:1.0target:self selector:@selector(test) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
ImageView显示只能在指定的model下设置图片PerformSelector只能在指定的model下调用[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageNamed:@"lnj"] waitUntilDone:YES modes:@[NSDefaultRunLoopMode]];
常驻线程必须调用run才会执行死循环NSRunLoop的model中必须有source/timer,死循环才不会退出NSRunLoop *runloop =[NSRunLoop currentRunLoop];
[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runloop run]
自动释放池activities =0x1=11: 即将进入RunLoop : 创建一个自动释放池
activities=0xa0=160=128+3232:即将休眠 : 释放上一次的自动释放池, 创建一个新的自动释放池128:即将退出RunLoop : 释放自动释放池