当前位置: 首页 > news >正文

wordpress qq 群太原企业网站seo

wordpress qq 群,太原企业网站seo,呢图网站,济南网站建设(选 聚搜网络)大厂常问iOS面试题–Runloop篇 一.RunLoop概念 RunLoop顾名思义就是可以一直循环(loop)运行(run)的机制。这种机制通常称为“消息循环机制” NSRunLoop和CFRunLoopRef就是实现“消息循环机制”的对象。其实NSRunLoop本质是由CFRunLoopRef封装的#xff0c;提供了面向对象的AP…大厂常问iOS面试题–Runloop篇 一.RunLoop概念 RunLoop顾名思义就是可以一直循环(loop)运行(run)的机制。这种机制通常称为“消息循环机制” NSRunLoop和CFRunLoopRef就是实现“消息循环机制”的对象。其实NSRunLoop本质是由CFRunLoopRef封装的提供了面向对象的API而CFRunLoopRef是一些面向过程的C函数API。两者最主要的区别在于NSRunLoop是非线程安全的意味着你不能用非当前线程去调用当前线程的NSRunLoop否则会出现意想不到的错误(You should never try to call the methods of an NSRunLoop object running in a different thread)。而CFRunLoopRef是线程安全的 RunLoop是通过内部维护的事件循环来对事件/消息进行管理的一个对象 它的关键点在于如何通过事件循环来管理事件/消息从而让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒 基本作用 保持程序的持续运行处理APP中的各种事件(触摸,定时器,GCD异步回到主线程,runloop中block回调的处理等)节省CPU资源,提供性能,该做事的时候做事,该休息的时候休息 Runloop 和线程的关系 一个线程对应一个 Runloop主线程默认就有了 Runloop而且默认是启动的子线程的 Runloop 以懒加载的形式创建默认是没有启动的如果你需要更多的线程交互则可以手动配置和启动如果线程只是去执行一个长时间的已确定的任务则不需要Runloop存储在一个全局的可变字典里线程是 key Runloop 是 value。 二.RunLoop的运行模式 RunLoop的运行模式共有5种RunLoop只会运行在一个模式下要切换模式就要暂停当前模式重写启动一个运行模式。model 主要作用是用来指定事件在运行循环中的优先级的。 kCFRunLoopDefaultMode-默认空闲状态 App的默认运行模式通常主线程是在这个运行模式下运行UITrackingRunLoopMode-ScrollView滑动时, 跟踪用户交互事件用于 ScrollView 追踪触摸滑动保证界面滑动时不受其他Mode影响kCFRunLoopCommonModes-Mode集合, 伪模式不是一种真正的运行模式UIInitializationRunLoopMode-启动时在刚启动App时第进入的第一个Mode启动完成后就不再使用GSEventReceiveRunLoopMode-接受系统内部事件通常用不到 三.Runloop内部逻辑 实际上 RunLoop 就是这样一个函数其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时线程就会一直停留在这个循环里直到超时或被手动停止该函数才会返回。 内部逻辑 1.通知观察者RunLoop已经启动 2.通知观察者即将要开始的定时器 3.通知观察者即将即将触发 Source0 (非port) 回调 4.触发 Source0 (非port) 回调。 5.如果有 Source1 (基于port) 处于 ready 状态直接处理这个 Source1 6.通知观察者线程进入休眠状态 7.将线程置于休眠直到任一下面的事件发生 某一事件到达 Source1 (基于port) 定时器启动 RunLoop设置的时间已经超时 RunLoop被显示唤醒例如手动调用CFRunLoopWakeUp 8.通知观察者线程将被唤醒 9.处理未处理的事件之后再跳回2 10.通知观察者RunLoop结束。 四.Runloop的使用场景 1.main.m中的autoreleasePool iOS的应用程序里面程序启动后main.m会有一个如下的main()函数为什么执行了main函数后app没有自动退出反而能一直响应用户消息呢 int main(int argc, char * argv[]) {autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));} }这是因为UIApplicationMain()函数这个方法会为main thread设置一个NSRunLoop对象这样就可以达到我们的应用在无人操作的时候休息需要让它干活的时候立马响应。 代码逻辑通常是这样的 function loop() {initialize();do {var message get_next_message();process_message(message);} while (message ! quit); }或使用伪代码来展示下: int main(int argc, char * argv[]) {//程序一直运行状态while (AppIsRunning) {//睡眠状态等待唤醒事件id whoWakesMe SleepForWakingUp();//得到唤醒事件id event GetEvent(whoWakesMe);//开始处理事件HandleEvent(event);}return 0; }这种模型通常被称作Event Loop。Event Loop在很多系统和框架里都有实现比如 Node.js 的事件处理比如Windows程序的消息循环再比如iOS里的 RunLoop 关于Runloop的事件循环 维护的事件循环,可以用来不断的处理消息或者事件,对他们进行管理当没有消息进行处理时,会从用户态发生到内核态的切换,由此可以用来当前线程的休眠,避免资源占用当有消息需要处理时,会发生从内核态到用户态的切换,当前的用户线程会被唤醒 用户态和内核态 用户态: 应用程序一般都是运行在用户态上,用户进程,包括我们开发所使用的绝大多数API,都是针对用户层面的内核态:在内核态往往有些陷阱指令,中断,以及一些开机关机的操作并且内核态里面的一些内容,可以对用户态中的一些线程进行调度和管理,包括进程间的通信 在用户态调用 mach_msg_trap() 时会触发陷阱机制切换到内核态内核态中内核实现的 mach_msg() 函数会完成实际的工作。RunLoop 的核心就是一个 mach_msg() RunLoop 调用这个函数去接收消息如果没有别人发送 port 消息过来内核会将线程置于等待状态。例如你在模拟器里跑起一个 iOS 的 App然后在 App 静止时点击暂停你会看到主线程调用栈是停留在 mach_msg_trap() 这个地方。 main函数为何能保持不退出?在UIApplicationMain函数内部会启动主线程的Runloop,可以不断的接收消息,比如点击屏幕事件,滑动列表以及处理网络请求的返回等接收消息后对事件进行处理,处理完之后,就会继续等待、休眠Runloop是对事件循环的一种维护机制可以做到在有事做的时候做事没有事情的时候会通过用户态发生到内核态的切换,避免资源占用当前线程处于休眠的状态。 autoreleasePool 在何时被释放 App启动后苹果在主线程 RunLoop 里注册了两个 Observer其回调都是 _wrapRunLoopWithAutoreleasePoolHandler()。第一个 Observer 监视的事件是 Entry(即将进入Loop)其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池。其 order 是 -2147483647优先级最高保证创建释放池发生在其他所有回调之前。第二个 Observer 监视了两个事件 BeforeWaiting(准备进入休眠) 时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647优先级最低保证其释放池子发生在其他所有回调之后。在主线程执行的代码通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着所以不会出现内存泄漏开发者也不必显示创建 Pool 了。 2.Runloop使用场景-GCD Runloop的超时时间就是通过GCD timer来控制的。GCD启动子线程内部其实用到了runloop。GCD从子线程返回到主线程会触发runloop的Source1事件 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{/// GCD往子线程丢一个延时操作能够执行说明GCD内部其实用到了runloop。NSLog(global after %, [NSThread currentThread]); });dispatch_async(main_queue, block)时libdispatch会向主线程的runloop发送消息唤醒runlooprunloop被唤醒后会从消息中获取block在callout函数 CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE 中执行该block任务。仅限主线程子线程的dispatch block操作全部由libdispatch完成的。 runloopMode dispatch_async(dispatch_get_main_queue(), …)会将block放到commonModes中执行而CFRunLoopPerformBlock允许指定runloopMode来执行block。 能否唤醒runloop dispatch_async(dispatch_get_main_queue(), …)会唤醒主线程的runloop而CFRunLoopPerformBlock不会主动唤醒runloop。如runloop休眠则CFRunLoopPerformBlock的block不能执行。可以使用CFRunLoopWakeUp来唤醒runloop。 GCD的main queue是一个串形队列 GCD的main queue是一个串形队列这样的结果就是dispatch_async(dispatch_get_main_queue(), …)传入的block会作为一个整体在runloop的下一次循环时执行。 请看如下代码输出 132是我们再也熟悉不过的代码了而后半部分为什么会 输出 456呢且等待的1s间隔时机也不一样分别为1…32和45…6。这里的…表示间隔 - (void)testGCDMainQueue {dispatch_async(dispatch_get_main_queue(), ^{NSLog(main queue task 1);dispatch_async(dispatch_get_main_queue(), ^{NSLog(main queue task 2);});[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];NSLog(main queue task 3);});/// 输出 132CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{NSLog(main queue task 4);CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{NSLog(main queue task 5);});[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];NSLog(main queue task 6);});/// 输出 456 }3.AFNetworking 中如何运用 Runloop AFURLConnectionOperation 这个类是基于 NSURLConnection 构建的其希望能在后台线程接收 Delegate 回调。为此 AFNetworking 单独创建了一个线程并在这个线程中启动了一个 RunLoop (void)networkRequestThreadEntryPoint:(id)__unused object {autoreleasepool {[[NSThread currentThread] setName:AFNetworking];NSRunLoop *runLoop [NSRunLoop currentRunLoop];[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];[runLoop run];} } (NSThread *)networkRequestThread {static NSThread *_networkRequestThread nil;static dispatch_once_t oncePredicate;dispatch_once(oncePredicate, ^{_networkRequestThread [[NSThread alloc] initWithTarget:self selector:selector(networkRequestThreadEntryPoint:) object:nil];[_networkRequestThread start];});return _networkRequestThread; }RunLoop 启动前内部必须要有至少一个 Timer/Observer/Source所以 AFNetworking 在 [runLoop run] 之前先创建了一个新的 NSMachPort 添加进去了。通常情况下调用者需要持有这个 NSMachPort (mach_port) 并在外部线程通过这个 port 发送消息到 loop 内但此处添加 port 只是为了让 RunLoop 不至于退出并没有用于实际的发送消息。 (void)start {[self.lock lock];if ([self isCancelled]) {[self performSelector:selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];} else if ([self isReady]) {self.state AFOperationExecutingState;[self performSelector:selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];}[self.lock unlock]; }当需要这个后台线程执行任务时AFNetworking 通过调用 [NSObject performSelector:onThread:…] 将这个任务扔到了后台线程的 RunLoop 中。 4.PerformSelector 的实现原理 当调用 NSObject 的 performSelecter:afterDelay: 后实际上其内部会创建一个 Timer 并添加到当前线程的 RunLoop 中。所以如果当前线程没有 RunLoop则这个方法会失效。当调用 performSelector:onThread: 时实际上其会创建一个 Timer 加到对应的线程去同样的如果对应线程没有 RunLoop 该方法也会失效。 5.PerformSelector:afterDelay:这个方法在子线程中是否起作用 不起作用子线程默认没有 Runloop也就没有 Timer。可以使用 GCD的dispatch_after来实现 6.以 scheduledTimerWithTimeInterval…的方式触发的timer在滑动页面上的列表时timer会暂停回调为什么如何解决 RunLoop只能运行在一种mode下如果要换mode当前的loop也需要停下重启成新的。利用这个机制ScrollView滚动过程中NSDefaultRunLoopModekCFRunLoopDefaultMode的mode会切换到UITrackingRunLoopMode来保证ScrollView的流畅滑动在NSDefaultRunLoopMode模式下处理的事件会影响ScrollView的滑动。 如果我们把一个NSTimer对象以NSDefaultRunLoopModekCFRunLoopDefaultMode添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换而导致NSTimer将不再被调度。 //1.创建Timer //2.自动添加到当前Runloop中,默认mode为kCFRunLoopDefaultMode //mode 为kCFRunLoopDefaultMode导致的问题当Scrollview滑动时会停止计时滑动结束后继续计时。 //原因当滑动Scrollview时。mode改变成为UITrackingRunLoopMode而timer添加到了默认模式下 NSDefaultRunLoopMode _timer1 [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:selector(handle:) userInfo:_timer1 repeats:YES];同时因为mode还是可定制的所以 Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModeskCFRunLoopCommonModes来解决。代码如下 //将timer添加到NSDefaultRunLoopMode中 [NSTimer scheduledTimerWithTimeInterval:1.0target:selfselector:selector(timerTick:)userInfo:nilrepeats:YES]; //然后再添加到NSRunLoopCommonModes里 NSTimer *timer [NSTimer timerWithTimeInterval:1.0target:selfselector:selector(timerTick:)userInfo:nilrepeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];6.事件响应的过程 苹果注册了一个 Source1 (基于 mach port 的) 用来接收系统事件其回调函数为 __IOHIDEventSystemClientQueueCallback()。当一个硬件事件(触摸/锁屏/摇晃等)发生后首先由 IOKit.framework 生成一个 IOHIDEvent 事件并由 SpringBoard 接收。这个过程的详细情况可以参考这里。SpringBoard 只接收按键(锁屏/静音等)触摸加速接近传感器等几种 Event随后用 mach port 转发给需要的 App 进程。随后苹果注册的那个 Source1 就会触发回调并调用 _UIApplicationHandleEventQueue() 进行应用内部的分发。_UIApplicationHandleEventQueue() 会把 IOHIDEvent 处理并包装成 UIEvent 进行处理或分发其中包括识别 UIGesture/处理屏幕旋转/发送给 UIWindow 等。通常事件比如 UIButton 点击、touchesBegin/Move/End/Cancel 事件都是在这个回调中完成的。 7.手势识别的过程 当 _UIApplicationHandleEventQueue() 识别了一个手势时其首先会调用 Cancel 将当前的 touchesBegin/Move/End 系列回调打断。随后系统将对应的 UIGestureRecognizer 标记为待处理。苹果注册了一个 Observer 监测 BeforeWaiting (Loop即将进入休眠) 事件这个 Observer 的回调函数是 _UIGestureRecognizerUpdateObserver()其内部会获取所有刚被标记为待处理的 GestureRecognizer并执行GestureRecognizer 的回调。当有 UIGestureRecognizer 的变化(创建/销毁/状态改变)时这个回调都会进行相应处理。 8.CADispalyTimer和Timer哪个更精确 CADisplayLink 更精确 iOS设备的屏幕刷新频率是固定的CADisplayLink在正常情况下会在每次刷新结束都被调用精确度相当高。NSTimer的精确度就显得低了点比如NSTimer的触发时间到的时候runloop如果在阻塞状态触发时间就会推迟到下一个runloop周期。并且 NSTimer新增了tolerance属性让用户可以设置可以容忍的触发的时间的延迟范围。CADisplayLink使用场合相对专一适合做UI的不停重绘比如自定义动画引擎或者视频播放的渲染。NSTimer的使用范围要广泛的多各种需要单次或者循环定时处理的任务都可以使用。在UI相关的动画或者显示内容使用 CADisplayLink比起用NSTimer的好处就是我们不需要在格外关心屏幕的刷新频率了因为它本身就是跟屏幕刷新同步的。
文章转载自:
http://www.morning.fnpyk.cn.gov.cn.fnpyk.cn
http://www.morning.sjsks.cn.gov.cn.sjsks.cn
http://www.morning.ydzly.cn.gov.cn.ydzly.cn
http://www.morning.flfxb.cn.gov.cn.flfxb.cn
http://www.morning.qmbgb.cn.gov.cn.qmbgb.cn
http://www.morning.pyncm.cn.gov.cn.pyncm.cn
http://www.morning.qdxkn.cn.gov.cn.qdxkn.cn
http://www.morning.txmkx.cn.gov.cn.txmkx.cn
http://www.morning.nfbkp.cn.gov.cn.nfbkp.cn
http://www.morning.yrflh.cn.gov.cn.yrflh.cn
http://www.morning.jpwmk.cn.gov.cn.jpwmk.cn
http://www.morning.cjmmn.cn.gov.cn.cjmmn.cn
http://www.morning.zmnyj.cn.gov.cn.zmnyj.cn
http://www.morning.rwpjq.cn.gov.cn.rwpjq.cn
http://www.morning.ggnkt.cn.gov.cn.ggnkt.cn
http://www.morning.tdfyj.cn.gov.cn.tdfyj.cn
http://www.morning.rnngz.cn.gov.cn.rnngz.cn
http://www.morning.tfzjl.cn.gov.cn.tfzjl.cn
http://www.morning.gcspr.cn.gov.cn.gcspr.cn
http://www.morning.rqkk.cn.gov.cn.rqkk.cn
http://www.morning.bmts.cn.gov.cn.bmts.cn
http://www.morning.hcsqznn.cn.gov.cn.hcsqznn.cn
http://www.morning.cfocyfa.cn.gov.cn.cfocyfa.cn
http://www.morning.pfkrw.cn.gov.cn.pfkrw.cn
http://www.morning.yqkxr.cn.gov.cn.yqkxr.cn
http://www.morning.dpwcl.cn.gov.cn.dpwcl.cn
http://www.morning.tjcgl.cn.gov.cn.tjcgl.cn
http://www.morning.xbzfz.cn.gov.cn.xbzfz.cn
http://www.morning.sjsks.cn.gov.cn.sjsks.cn
http://www.morning.qcfgd.cn.gov.cn.qcfgd.cn
http://www.morning.ccpnz.cn.gov.cn.ccpnz.cn
http://www.morning.rjjjk.cn.gov.cn.rjjjk.cn
http://www.morning.jpgfq.cn.gov.cn.jpgfq.cn
http://www.morning.kzbpx.cn.gov.cn.kzbpx.cn
http://www.morning.snmsq.cn.gov.cn.snmsq.cn
http://www.morning.kwwkm.cn.gov.cn.kwwkm.cn
http://www.morning.thpns.cn.gov.cn.thpns.cn
http://www.morning.wypyl.cn.gov.cn.wypyl.cn
http://www.morning.jkszt.cn.gov.cn.jkszt.cn
http://www.morning.gtnyq.cn.gov.cn.gtnyq.cn
http://www.morning.ysybx.cn.gov.cn.ysybx.cn
http://www.morning.rmfwh.cn.gov.cn.rmfwh.cn
http://www.morning.kfmlf.cn.gov.cn.kfmlf.cn
http://www.morning.ysbhj.cn.gov.cn.ysbhj.cn
http://www.morning.tfgkq.cn.gov.cn.tfgkq.cn
http://www.morning.mlntx.cn.gov.cn.mlntx.cn
http://www.morning.llllcc.com.gov.cn.llllcc.com
http://www.morning.mgtrc.cn.gov.cn.mgtrc.cn
http://www.morning.wsxxq.cn.gov.cn.wsxxq.cn
http://www.morning.dskmq.cn.gov.cn.dskmq.cn
http://www.morning.gwwky.cn.gov.cn.gwwky.cn
http://www.morning.ptqds.cn.gov.cn.ptqds.cn
http://www.morning.xfxqj.cn.gov.cn.xfxqj.cn
http://www.morning.yjknk.cn.gov.cn.yjknk.cn
http://www.morning.qsy37.cn.gov.cn.qsy37.cn
http://www.morning.jrdbq.cn.gov.cn.jrdbq.cn
http://www.morning.kphsp.cn.gov.cn.kphsp.cn
http://www.morning.rxlck.cn.gov.cn.rxlck.cn
http://www.morning.bpmtz.cn.gov.cn.bpmtz.cn
http://www.morning.dsgdt.cn.gov.cn.dsgdt.cn
http://www.morning.thwhn.cn.gov.cn.thwhn.cn
http://www.morning.zhoer.com.gov.cn.zhoer.com
http://www.morning.nnwpz.cn.gov.cn.nnwpz.cn
http://www.morning.bkqw.cn.gov.cn.bkqw.cn
http://www.morning.jsljr.cn.gov.cn.jsljr.cn
http://www.morning.qcbhb.cn.gov.cn.qcbhb.cn
http://www.morning.lbbgf.cn.gov.cn.lbbgf.cn
http://www.morning.xctdn.cn.gov.cn.xctdn.cn
http://www.morning.plhyc.cn.gov.cn.plhyc.cn
http://www.morning.xpzrx.cn.gov.cn.xpzrx.cn
http://www.morning.dmcqy.cn.gov.cn.dmcqy.cn
http://www.morning.eshixi.com.gov.cn.eshixi.com
http://www.morning.snlxb.cn.gov.cn.snlxb.cn
http://www.morning.wgrl.cn.gov.cn.wgrl.cn
http://www.morning.lsyk.cn.gov.cn.lsyk.cn
http://www.morning.rjrnx.cn.gov.cn.rjrnx.cn
http://www.morning.wcyr.cn.gov.cn.wcyr.cn
http://www.morning.hkcjx.cn.gov.cn.hkcjx.cn
http://www.morning.kmrgl.cn.gov.cn.kmrgl.cn
http://www.morning.pffqh.cn.gov.cn.pffqh.cn
http://www.tj-hxxt.cn/news/223140.html

相关文章:

  • 做公司网站的流程网站开发运营职位
  • 建设快照网站意大利天天电信app下载
  • 山东网站建设空间新品上市新闻稿
  • 社交网站是怎么做的wordpress的页脚模板修改就出错
  • 做一个卖车的网站该怎么做有人有片视频吗免费的下载
  • 网站制作潍坊区域网页定制哪家不错
  • 馆陶网站推广网站名称注册保护
  • 网站建设的类型有几种施工企业工程施工科目
  • 阿里网站备案寄材料济南专业做网站的公司
  • 千牛商家版网站建设长沙做网站建设价格
  • 网站建设使用情况常德公交网站
  • iis配置网站权限牡丹江信息网手机版招聘
  • 鲜花网站建设店专业网页设计费用
  • 蚌埠做网站深圳企业专业网站建设
  • 免费自己做网站软件网站备案成功怎么查备案号
  • 做网站的流程网站建设方案详解
  • 义安区住房和城乡建设局建网站生成图标网站
  • 网站建设与制作流程有个网站可以学做ppt模板
  • 外贸网站设计师天津河东区网站建设
  • 电子口岸网站做资料库石家庄住建局网站
  • 构建一个网站简答题网站建设步骤
  • 东莞市住房和城乡建设厅网站首页微网站设计与开发
  • 网站备案多久可以注销大型门户网站建设费用
  • 做一名优秀网站设计师计划设计大赛官网
  • 做网站sqlserver排序百度seo服务
  • 长春自主建站模板word wordpress
  • 做301跳转会影响之前网站排名吗奖励自己视频免费
  • 网站建设销售客户疑问重庆装修设计网站
  • 网站建设英语词汇微网站建设服务商
  • 东莞建网站郑州市建设局官网