理解RunLoop:概念、底层实现及苹果的应用。

需积分: 0 0 下载量 167 浏览量 更新于2024-01-19 收藏 1.69MB PDF 举报
深入理解RunLoop RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,它负责处理事件和任务的调度和分发。本文将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理。之后会介绍一下在 iOS 中,苹果是如何利用RunLoop 实现自动释放池、延迟回调、触摸事件、屏幕刷新等功能的。 一、RunLoop的概念 RunLoop是一个事件循环机制,其作用是在一个线程中负责处理事件和任务的调度。它可以说是一种消息循环机制,不断地从消息队列中取出消息并处理。当消息队列中没有消息时,RunLoop会进入休眠状态,等待新的事件到来。 二、RunLoop与线程的关系 每个线程在运行时都会默认拥有一个RunLoop,但并不是所有线程都需要RunLoop。主线程会自动创建并启动RunLoop,而子线程则需要手动创建和启动RunLoop。 三、RunLoop对外的接口 RunLoop对外提供了一组API来管理当前线程的RunLoop。其中最常用的是CFRunLoopGetCurrent()和CFRunLoopRun(),分别用于获取当前线程的RunLoop和启动该RunLoop。 四、RunLoop的Mode RunLoop有多个Mode,每个Mode下又有多个Source、Observer和Timer。这些不同的Mode可以控制RunLoop在不同的场景下响应不同类型的事件。 五、RunLoop的内部逻辑 RunLoop内部是由一个do-while循环组成的。在每次循环开始前,RunLoop会先检查是否有需要立即唤醒的Source,如有则立即处理。接着,RunLoop会检查是否有定时器需要触发,如有则触发定时器的回调。然后,RunLoop会检查是否有事务要提交,如有则提交事务。最后,RunLoop会根据当前Mode的状态判断是否需要休眠。若当前Mode下没有Source、Observer和Timer,并且已经执行了一次空闲回调,RunLoop就会进入休眠状态,直到被唤醒。 六、RunLoop的底层实现 RunLoop的底层实现是基于事件驱动的机制。在底层,RunLoop通过内核实现了一个事件队列,不断地从队列中获取事件并处理。当事件队列为空时,RunLoop会进入休眠状态,直到有新的事件到来。 七、苹果用RunLoop实现的功能 苹果在底层利用RunLoop实现了一些常用的功能,包括自动释放池、延迟回调、触摸事件、屏幕刷新等。这些功能都是通过RunLoop在合适的时机处理相应的事件来实现的。 1. AutoreleasePool 在每个RunLoop的开始和结束时,苹果会自动创建和释放一个AutoreleasePool。这样,我们可以在一个RunLoop周期内创建大量的临时对象,当RunLoop执行结束时,自动释放这些对象,避免内存泄漏。 2. 事件响应 当用户触摸屏幕时,系统会将触摸事件添加到当前RunLoop的事件队列中。RunLoop会不断地从事件队列中取出事件并传递给相应的Responder进行处理。 3. 手势识别 手势识别是建立在触摸事件的基础上的。当用户触摸屏幕时,RunLoop会将触摸事件传递给手势识别器来判断用户的手势操作,并执行相应的操作。 4. 界面更新 界面更新是基于屏幕刷新的机制。RunLoop会根据屏幕的刷新率来定时调用界面更新相关的方法,以实现平滑的界面显示。 5. 定时器 定时器是利用RunLoop的定时器功能实现的。我们可以创建一个定时器,并指定它在未来的某个时间点触发回调,RunLoop会在指定的时间点执行相应的回调操作。 八、RunLoop的实际应用举例 在实际开发中,RunLoop有许多应用场景。以下是一些常见的使用案例: 1. AFNetworking AFNetworking是一个非常流行的网络请求框架,它利用RunLoop来管理网络请求的发送和接收。通过RunLoop的机制,AFNetworking可以实现网络请求的异步操作,从而不会阻塞主线程的执行。 2. AsyncDisplayKit AsyncDisplayKit是一个高性能的UI框架,它利用RunLoop来实现异步绘制和布局。通过RunLoop的机制,AsyncDisplayKit可以将耗时的绘制和布局操作移到后台线程,提升UI的流畅性和响应速度。 以上就是对RunLoop的深入理解的总结。RunLoop是iOS和OSX开发中非常重要的一个概念,它不仅可以帮助我们实现一些常用的功能,还可以提升应用的性能和响应速度。希望本文对你深入理解RunLoop有所帮助。
2023-07-14 上传

Exception in Application constructor Exception in thread "main" java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1071) Caused by: java.lang.RuntimeException: Unable to construct Application instance: class com.example.demo.Main at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:891) at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: java.lang.IllegalAccessException: class com.sun.javafx.application.LauncherImpl (in module javafx.graphics) cannot access class com.example.demo.Main (in module com.example.javafxtest) because module com.example.javafxtest does not export com.example.demo to module javafx.graphics at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392) at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:489) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:803) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456) at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96) at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184) ... 1 more

2023-05-24 上传