@@ -11,34 +11,34 @@ import Foundation
1111import UIKit
1212
1313public protocol iOSLifecycle {
14- func applicationDidEnterBackground( application: UIApplication )
15- func applicationWillEnterForeground( application: UIApplication )
16- func application( _ application: UIApplication , didFinishLaunchingWithOptions launchOptions: [ UIApplication . LaunchOptionsKey : Any ] ? )
17- func applicationDidBecomeActive( application: UIApplication )
18- func applicationWillResignActive( application: UIApplication )
19- func applicationDidReceiveMemoryWarning( application: UIApplication )
20- func applicationWillTerminate( application: UIApplication )
21- func applicationSignificantTimeChange( application: UIApplication )
22- func applicationBackgroundRefreshDidChange( application: UIApplication , refreshStatus: UIBackgroundRefreshStatus )
14+ func applicationDidEnterBackground( application: UIApplication ? )
15+ func applicationWillEnterForeground( application: UIApplication ? )
16+ func application( _ application: UIApplication ? , didFinishLaunchingWithOptions launchOptions: [ UIApplication . LaunchOptionsKey : Any ] ? )
17+ func applicationDidBecomeActive( application: UIApplication ? )
18+ func applicationWillResignActive( application: UIApplication ? )
19+ func applicationDidReceiveMemoryWarning( application: UIApplication ? )
20+ func applicationWillTerminate( application: UIApplication ? )
21+ func applicationSignificantTimeChange( application: UIApplication ? )
22+ func applicationBackgroundRefreshDidChange( application: UIApplication ? , refreshStatus: UIBackgroundRefreshStatus )
2323}
2424
2525public extension iOSLifecycle {
26- func applicationDidEnterBackground( application: UIApplication ) { }
27- func applicationWillEnterForeground( application: UIApplication ) { }
28- func application( _ application: UIApplication , didFinishLaunchingWithOptions launchOptions: [ UIApplication . LaunchOptionsKey : Any ] ? ) { }
29- func applicationDidBecomeActive( application: UIApplication ) { }
30- func applicationWillResignActive( application: UIApplication ) { }
31- func applicationDidReceiveMemoryWarning( application: UIApplication ) { }
32- func applicationWillTerminate( application: UIApplication ) { }
33- func applicationSignificantTimeChange( application: UIApplication ) { }
34- func applicationBackgroundRefreshDidChange( application: UIApplication , refreshStatus: UIBackgroundRefreshStatus ) { }
26+ func applicationDidEnterBackground( application: UIApplication ? ) { }
27+ func applicationWillEnterForeground( application: UIApplication ? ) { }
28+ func application( _ application: UIApplication ? , didFinishLaunchingWithOptions launchOptions: [ UIApplication . LaunchOptionsKey : Any ] ? ) { }
29+ func applicationDidBecomeActive( application: UIApplication ? ) { }
30+ func applicationWillResignActive( application: UIApplication ? ) { }
31+ func applicationDidReceiveMemoryWarning( application: UIApplication ? ) { }
32+ func applicationWillTerminate( application: UIApplication ? ) { }
33+ func applicationSignificantTimeChange( application: UIApplication ? ) { }
34+ func applicationBackgroundRefreshDidChange( application: UIApplication ? , refreshStatus: UIBackgroundRefreshStatus ) { }
3535}
3636
3737class iOSLifecycleMonitor : PlatformPlugin {
3838 let type = PluginType . utility
3939 var analytics : Analytics ?
4040
41- private var application : UIApplication
41+ private var application : UIApplication ? = nil
4242 private var appNotifications : [ NSNotification . Name ] = [ UIApplication . didEnterBackgroundNotification,
4343 UIApplication . willEnterForegroundNotification,
4444 UIApplication . didFinishLaunchingNotification,
@@ -50,7 +50,9 @@ class iOSLifecycleMonitor: PlatformPlugin {
5050 UIApplication . backgroundRefreshStatusDidChangeNotification]
5151
5252 required init ( ) {
53- application = UIApplication . shared
53+ // App extensions can't use UIAppication.shared, so
54+ // funnel it through something to check; Could be nil.
55+ application = UIApplication . safeShared
5456 setupListeners ( )
5557 }
5658
@@ -154,10 +156,15 @@ class iOSLifecycleMonitor: PlatformPlugin {
154156 }
155157
156158 func backgroundRefreshDidChange( notification: NSNotification ) {
157- analytics? . apply { ( ext) in
158- if let validExt = ext as? iOSLifecycle {
159- validExt. applicationBackgroundRefreshDidChange ( application: application,
160- refreshStatus: application. backgroundRefreshStatus)
159+ // Not only would we not get this in an App Extension, but it would
160+ // be useless since we couldn't provide the application object or
161+ // the refreshStatus value.
162+ if !isAppExtension, let application = UIApplication . safeShared {
163+ analytics? . apply { ( ext) in
164+ if let validExt = ext as? iOSLifecycle {
165+ validExt. applicationBackgroundRefreshDidChange ( application: application,
166+ refreshStatus: application. backgroundRefreshStatus)
167+ }
161168 }
162169 }
163170 }
@@ -166,11 +173,11 @@ class iOSLifecycleMonitor: PlatformPlugin {
166173// MARK: - Segment Destination Extension
167174
168175extension SegmentDestination : iOSLifecycle {
169- public func applicationWillEnterForeground( application: UIApplication ) {
176+ public func applicationWillEnterForeground( application: UIApplication ? ) {
170177 enterForeground ( )
171178 }
172179
173- public func applicationDidEnterBackground( application: UIApplication ) {
180+ public func applicationDidEnterBackground( application: UIApplication ? ) {
174181 enterBackground ( )
175182 }
176183}
@@ -180,15 +187,36 @@ extension SegmentDestination.UploadTaskInfo {
180187 self . url = url
181188 self . task = task
182189
183- let taskIdentifier = UIApplication . shared. beginBackgroundTask { [ self ] in
184- self . task. suspend ( )
185- self . cleanup ? ( )
190+ if let application = UIApplication . safeShared {
191+ let taskIdentifier = application. beginBackgroundTask { [ self ] in
192+ self . task. suspend ( )
193+ self . cleanup ? ( )
194+ }
195+ self . taskID = taskIdentifier. rawValue
196+
197+ self . cleanup = { [ self ] in
198+ application. endBackgroundTask ( UIBackgroundTaskIdentifier ( rawValue: self . taskID) )
199+ }
186200 }
187- self . taskID = taskIdentifier. rawValue
201+ }
202+ }
203+
204+ extension UIApplication {
205+ static var safeShared : UIApplication ? {
206+ // UIApplication.shared is not available in app extensions so try to get
207+ // it in a way that's safe for both.
188208
189- self . cleanup = { [ self ] in
190- UIApplication . shared. endBackgroundTask ( UIBackgroundTaskIdentifier ( rawValue: self . taskID) )
209+ // if we are NOT an app extension, we need to get UIApplication.shared
210+ if !isAppExtension {
211+ // getting it like this allows us to avoid the compiler error that would
212+ // be generated even though we're guarding against app extensions.
213+ // there's no preprocessor macro or @available macro to help us here unfortunately
214+ // so this is the best i could do.
215+ return UIApplication . value ( forKeyPath: " sharedApplication " ) as? UIApplication
191216 }
217+ // if we ARE an app extension, send back nil since we have no way to get the
218+ // application instance.
219+ return nil
192220 }
193221}
194222
0 commit comments