Skip to content

Commit 4af9d49

Browse files
authored
Merge pull request #271 from IFTTT/feature/background_process_hook
Adding hooks that can be used to execute code when the system runs a background process
2 parents 4a256f7 + 3c861e2 commit 4af9d49

File tree

7 files changed

+48
-8
lines changed

7 files changed

+48
-8
lines changed

Examples/GroceryExpress/AppDelegate.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
2424
ConnectButtonController.analyticsEnabled = true
2525
ConnectButtonController.initialize(options: .init(enableSDKBackgroundProcess: true, showPermissionsPrompts: true))
2626
ConnectButtonController.activate(connections: [DisplayInformation.locationConnection.connectionId])
27+
ConnectButtonController.setBackgroundProcessClosures {
28+
print("Background process started!")
29+
} expirationHandler: {
30+
print("Background process expired!")
31+
}
32+
2733
return true
2834
}
2935

IFTTT SDK/ConnectButton+Constants.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation
99

10-
typealias VoidClosure = () -> Void
10+
public typealias VoidClosure = () -> Void
1111

1212
extension ConnectButton {
1313

IFTTT SDK/ConnectButtonController+Public.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,16 @@ extension ConnectButtonController {
153153
public static func geofencesEnabled(for connectionId: String) -> Bool {
154154
return ConnectionsSynchronizer.shared.geofencesEnabled(for: connectionId)
155155
}
156+
157+
/// Allows for a closure to be executed when the OS starts a background process set up by the SDK.
158+
///
159+
/// The `launchHandler` parameter will get run on a background thread. `expirationHandler` gets called by the system right before the amount of allotted time for the background process is zero. Use the `expirationHandler` to perform any cleanup of resources used or allocated in `launchHandler`. `expirationHandler` will be executed on the same background thread as `launchHandler`.
160+
///
161+
/// - Parameters:
162+
/// - launchHandler: A closure to execute when the OS starts a background process set up by the SDK.
163+
/// - expirationHandler: A closure to execute when the allotted time for the background process is zero.
164+
public static func setBackgroundProcessClosures(launchHandler: VoidClosure?, expirationHandler: VoidClosure?) {
165+
ConnectionsSynchronizer.shared.setDeveloperBackgroundProcessClosures(launchHandler: launchHandler,
166+
expirationHandler: expirationHandler)
167+
}
156168
}

IFTTT SDK/ConnectionsSynchronizer.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ final class ConnectionsSynchronizer {
278278
func geofencesEnabled(for connectionId: String) -> Bool {
279279
return registry.geofencesEnabled(connectionId: connectionId)
280280
}
281+
282+
func setDeveloperBackgroundProcessClosures(launchHandler: VoidClosure?, expirationHandler: VoidClosure?) {
283+
scheduler.developerBackgroundProcessLaunchClosure = launchHandler
284+
scheduler.developerBackgroundProcessExpirationClosure = expirationHandler
285+
}
281286
}
282287

283288
/// Handles coordination of native services with a set of connections

IFTTT SDK/SynchronizationScheduler.swift

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ final class SynchronizationScheduler {
3535
/// A closure that gets invoked after an authentication failure in a sync task
3636
var onAuthenticationFailure: VoidClosure?
3737

38+
/// A `DispatchQueue` to use in executing `developerBackgroundProcessClosure`.
39+
private let developerBackgroundProcessDispatchQueue = DispatchQueue(label: "com.ifttt.backgroundprocess.developer_closure")
40+
41+
/// A closure that's passed in by the developer to execute when a background process handler gets called.
42+
var developerBackgroundProcessLaunchClosure: VoidClosure?
43+
44+
/// A closure that's called when expiration of the background process occurs. This is supplied by the developer.
45+
var developerBackgroundProcessExpirationClosure: VoidClosure?
46+
3847
/// Creates a `SyncScheduler`
3948
///
4049
/// - Parameters:
@@ -236,12 +245,20 @@ extension SynchronizationScheduler {
236245
private func registerBackgroundProcess() {
237246
BGTaskScheduler.shared.register(forTaskWithIdentifier: SynchronizationScheduler.BackgroundProcessIdentifier, using: nil) { [weak self] (task) in
238247
guard let appProcessTask = task as? BGProcessingTask else { return }
239-
240-
self?.scheduleBackgroundProcess()
241248

249+
self?.scheduleBackgroundProcess()
242250
appProcessTask.expirationHandler = {
243-
ConnectButtonController.synchronizationLog("Synchronization took too long, expiration handler invoked")
244-
self?.manager.currentTask?.cancel()
251+
self?.developerBackgroundProcessDispatchQueue.async {
252+
self?.developerBackgroundProcessExpirationClosure?()
253+
}
254+
255+
ConnectButtonController.synchronizationLog("Synchronization took too long, expiration handler invoked")
256+
self?.manager.currentTask?.cancel()
257+
appProcessTask.setTaskCompleted(success: true)
258+
}
259+
260+
self?.developerBackgroundProcessDispatchQueue.async {
261+
self?.developerBackgroundProcessLaunchClosure?()
245262
}
246263

247264
self?.manager.sync(source: .internalBackgroundProcess) { (result, authenticationFailure) in

Location.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ The SDK doesn't directly invoke any background fetch methods. To use background
8282
### Geofence Toggling
8383
The SDK supports toggling geofences on and off for a given connection. To toggle geofences for a connection, call `ConnectButtonController.setGeofencesEnabled(enabled:for:)`.
8484
85+
### Background process execution
86+
To set closures to run when a SDK-defined background process runs, call `ConnectButtonController.setBackgroundProcessClosures(launchHandler:expirationHandler)`. The `launchHandler` parameter is the closure that's executed when a background process starts. The `expirationHandler` parameter is the closure that's executed when the background process is about to be ended by the system.
87+
8588
### Notes
8689
- Automatic synchronization for a given connection will only be run if the connection has location triggers. Similarly, location region monitoring will only be started if the connection has location triggers setup.
8790
- The SDK runs a synchronization by default for the following events:

SDKHostApp/AppDelegate.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import UIKit
1010

1111
@main
1212
class AppDelegate: UIResponder, UIApplicationDelegate {
13-
14-
15-
1613
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
1714
// Override point for customization after application launch.
1815
return true

0 commit comments

Comments
 (0)