@@ -13,8 +13,14 @@ use core_foundation::runloop::{
1313} ;
1414use objc2:: rc:: Retained ;
1515use objc2:: { msg_send_id, ClassType } ;
16- use objc2_foundation:: { MainThreadMarker , NSString } ;
17- use objc2_ui_kit:: { UIApplication , UIApplicationMain , UIDevice , UIScreen , UIUserInterfaceIdiom } ;
16+ use objc2_foundation:: { MainThreadMarker , NSNotificationCenter , NSObject } ;
17+ use objc2_ui_kit:: {
18+ UIApplication , UIApplicationDidBecomeActiveNotification ,
19+ UIApplicationDidEnterBackgroundNotification , UIApplicationDidFinishLaunchingNotification ,
20+ UIApplicationDidReceiveMemoryWarningNotification , UIApplicationMain ,
21+ UIApplicationWillEnterForegroundNotification , UIApplicationWillResignActiveNotification ,
22+ UIApplicationWillTerminateNotification , UIDevice , UIScreen , UIUserInterfaceIdiom ,
23+ } ;
1824
1925use crate :: error:: EventLoopError ;
2026use crate :: event:: Event ;
@@ -25,8 +31,8 @@ use crate::platform::ios::Idiom;
2531use crate :: platform_impl:: ios:: app_state:: { EventLoopHandler , HandlePendingUserEvents } ;
2632use crate :: window:: { CustomCursor , CustomCursorSource , Theme } ;
2733
28- use super :: app_delegate :: AppDelegate ;
29- use super :: app_state :: AppState ;
34+ use super :: app_state :: { send_occluded_event_for_all_windows , AppState , EventWrapper } ;
35+ use super :: notification_center :: create_observer ;
3036use super :: { app_state, monitor, MonitorHandle } ;
3137
3238#[ derive( Debug ) ]
@@ -132,6 +138,18 @@ pub struct EventLoop<T: 'static> {
132138 sender : Sender < T > ,
133139 receiver : Receiver < T > ,
134140 window_target : RootActiveEventLoop ,
141+
142+ // Since iOS 9.0, we no longer need to remove the observers before they are deallocated; the
143+ // system instead cleans it up next time it would have posted a notification to it.
144+ //
145+ // Though we do still need to keep the observers around to prevent them from being deallocated.
146+ _did_finish_launching_observer : Retained < NSObject > ,
147+ _did_become_active_observer : Retained < NSObject > ,
148+ _will_resign_active_observer : Retained < NSObject > ,
149+ _will_enter_foreground_observer : Retained < NSObject > ,
150+ _did_enter_background_observer : Retained < NSObject > ,
151+ _will_terminate_observer : Retained < NSObject > ,
152+ _did_receive_memory_warning_observer : Retained < NSObject > ,
135153}
136154
137155#[ derive( Default , Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
@@ -158,11 +176,97 @@ impl<T: 'static> EventLoop<T> {
158176 // this line sets up the main run loop before `UIApplicationMain`
159177 setup_control_flow_observers ( ) ;
160178
179+ let center = unsafe { NSNotificationCenter :: defaultCenter ( ) } ;
180+
181+ let _did_finish_launching_observer = create_observer (
182+ & center,
183+ // `application:didFinishLaunchingWithOptions:`
184+ unsafe { UIApplicationDidFinishLaunchingNotification } ,
185+ move |_| {
186+ app_state:: did_finish_launching ( mtm) ;
187+ } ,
188+ ) ;
189+ let _did_become_active_observer = create_observer (
190+ & center,
191+ // `applicationDidBecomeActive:`
192+ unsafe { UIApplicationDidBecomeActiveNotification } ,
193+ move |_| {
194+ app_state:: handle_nonuser_event ( mtm, EventWrapper :: StaticEvent ( Event :: Resumed ) ) ;
195+ } ,
196+ ) ;
197+ let _will_resign_active_observer = create_observer (
198+ & center,
199+ // `applicationWillResignActive:`
200+ unsafe { UIApplicationWillResignActiveNotification } ,
201+ move |_| {
202+ app_state:: handle_nonuser_event ( mtm, EventWrapper :: StaticEvent ( Event :: Suspended ) ) ;
203+ } ,
204+ ) ;
205+ let _will_enter_foreground_observer = create_observer (
206+ & center,
207+ // `applicationWillEnterForeground:`
208+ unsafe { UIApplicationWillEnterForegroundNotification } ,
209+ move |notification| {
210+ let app = unsafe { notification. object ( ) } . expect (
211+ "UIApplicationWillEnterForegroundNotification to have application object" ,
212+ ) ;
213+ // SAFETY: The `object` in `UIApplicationWillEnterForegroundNotification` is
214+ // documented to be `UIApplication`.
215+ let app: Retained < UIApplication > = unsafe { Retained :: cast ( app) } ;
216+ send_occluded_event_for_all_windows ( & app, false ) ;
217+ } ,
218+ ) ;
219+ let _did_enter_background_observer = create_observer (
220+ & center,
221+ // `applicationDidEnterBackground:`
222+ unsafe { UIApplicationDidEnterBackgroundNotification } ,
223+ move |notification| {
224+ let app = unsafe { notification. object ( ) } . expect (
225+ "UIApplicationDidEnterBackgroundNotification to have application object" ,
226+ ) ;
227+ // SAFETY: The `object` in `UIApplicationDidEnterBackgroundNotification` is
228+ // documented to be `UIApplication`.
229+ let app: Retained < UIApplication > = unsafe { Retained :: cast ( app) } ;
230+ send_occluded_event_for_all_windows ( & app, true ) ;
231+ } ,
232+ ) ;
233+ let _will_terminate_observer = create_observer (
234+ & center,
235+ // `applicationWillTerminate:`
236+ unsafe { UIApplicationWillTerminateNotification } ,
237+ move |notification| {
238+ let app = unsafe { notification. object ( ) }
239+ . expect ( "UIApplicationWillTerminateNotification to have application object" ) ;
240+ // SAFETY: The `object` in `UIApplicationWillTerminateNotification` is
241+ // (somewhat) documented to be `UIApplication`.
242+ let app: Retained < UIApplication > = unsafe { Retained :: cast ( app) } ;
243+ app_state:: terminated ( & app) ;
244+ } ,
245+ ) ;
246+ let _did_receive_memory_warning_observer = create_observer (
247+ & center,
248+ // `applicationDidReceiveMemoryWarning:`
249+ unsafe { UIApplicationDidReceiveMemoryWarningNotification } ,
250+ move |_| {
251+ app_state:: handle_nonuser_event (
252+ mtm,
253+ EventWrapper :: StaticEvent ( Event :: MemoryWarning ) ,
254+ ) ;
255+ } ,
256+ ) ;
257+
161258 Ok ( EventLoop {
162259 mtm,
163260 sender,
164261 receiver,
165262 window_target : RootActiveEventLoop { p : ActiveEventLoop { mtm } , _marker : PhantomData } ,
263+ _did_finish_launching_observer,
264+ _did_become_active_observer,
265+ _will_resign_active_observer,
266+ _will_enter_foreground_observer,
267+ _did_enter_background_observer,
268+ _will_terminate_observer,
269+ _did_receive_memory_warning_observer,
166270 } )
167271 }
168272
@@ -192,9 +296,6 @@ impl<T: 'static> EventLoop<T> {
192296
193297 app_state:: will_launch ( self . mtm , handler) ;
194298
195- // Ensure application delegate is initialized
196- let _ = AppDelegate :: class ( ) ;
197-
198299 extern "C" {
199300 // These functions are in crt_externs.h.
200301 fn _NSGetArgc ( ) -> * mut c_int ;
@@ -205,8 +306,10 @@ impl<T: 'static> EventLoop<T> {
205306 UIApplicationMain (
206307 * _NSGetArgc ( ) ,
207308 NonNull :: new ( * _NSGetArgv ( ) ) . unwrap ( ) ,
309+ // We intentionally override neither the application nor the delegate, to allow the
310+ // user to do so themselves!
311+ None ,
208312 None ,
209- Some ( & NSString :: from_str ( AppDelegate :: NAME ) ) ,
210313 )
211314 } ;
212315 unreachable ! ( )
0 commit comments