18 Commits

Author SHA1 Message Date
Fernando Martín Ortiz 465ebe3f64 Merge pull request #25 from davbeck/master
Fix callback handling
2017-11-08 19:18:25 -03:00
David Beck 89deaa7850 Fix callback handling
Callbacks need to be coallesced for multiple responders, and more importantly, called if no service responds.
2017-08-29 14:12:53 -07:00
Fernando Martín Ortiz e03cd1e487 Merge pull request #18 from stephanecopin/public-fix
Fix issue where open url was changed to public url
2017-05-23 16:51:26 -03:00
Stéphane Copin 704d2c7d30 Fix issue where open url was changed to public url 2017-05-18 14:14:16 +01:00
Fernando 97ead7c308 Solved warnings. 2017-05-16 09:52:34 -03:00
Fernando Martín Ortiz 66cbdc3f78 Merge pull request #17 from adamchalmers/master
Changed lifecycle methods from public to open
2017-05-15 15:43:20 -03:00
Adam Chalmers 50a8cb44cf Changed lifecycle methods from public to open
My company is using PluggableApplicationDelegate in our iOS codebase. We'd like to time each ApplicationService's didFinishLaunching and didBecomeActive methods, to find where we can get performance gains. My initial thought was to subclass PluggableApplicationDelegate and add timers to the relevant methods, but because they're public (not open) this isn't possible.
2017-05-15 13:18:17 -05:00
Fernando Martín Ortiz d129ee2680 Merge pull request #15 from stephanecopin/logic-refactor
Fix delegate method handling
2017-05-15 11:51:23 -03:00
Stéphane Copin 4119d0395f Fix logic when calling delegate methods from multiple services, so that they're never short-circuited. 2017-05-15 15:39:06 +01:00
Fernando Martín Ortiz 3ae9dbacc7 Merge pull request #11 from andrewcb/master
Boolean methods made more concise and functional by replacing loops with reduce expressions
2017-04-20 10:56:14 -03:00
acb dbc8e1e745 Boolean methods made more concise and functional by replacing loops with reduce expressions 2017-04-12 12:56:22 +01:00
Fernando Martín Ortiz 8e9091f109 Merge pull request #9 from DKOG/master
Remove `:git =>` from the podfile installation string
2017-04-07 11:49:13 -03:00
Daniel Kloeck 3a045a0904 Remove :git => from the podfile installation string 2017-04-07 10:34:35 +02:00
Fernando Martín Ortiz 4ed80bf050 Merge pull request #7 from harmjanr/master
Changed return value
2017-04-04 17:47:38 -03:00
Harm-Jan Roskam 283cf142f3 Return result instead of true. The whole for loop is useless if true is returned. 2017-04-04 15:05:11 +02:00
Fernando Ortiz e400f10779 Merge branch 'master' of https://github.com/fmo91/PluggableApplicationDelegate 2017-04-04 01:12:13 -03:00
Fernando Martín Ortiz c20435566e Merge pull request #6 from loopsocial/feature/carthage
Share the main scheme so Carthage can pick it up
2017-04-03 23:46:35 -03:00
Jakub Petrík f12323e1b0 Share main scheme 2017-04-03 13:25:08 -07:00
4 changed files with 238 additions and 123 deletions
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "650D907715EF6AB8D20EC59213D27791"
BuildableName = "PluggableApplicationDelegate.framework"
BlueprintName = "PluggableApplicationDelegate"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "650D907715EF6AB8D20EC59213D27791"
BuildableName = "PluggableApplicationDelegate.framework"
BlueprintName = "PluggableApplicationDelegate"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "650D907715EF6AB8D20EC59213D27791"
BuildableName = "PluggableApplicationDelegate.framework"
BlueprintName = "PluggableApplicationDelegate"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
+1 -1
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'PluggableApplicationDelegate'
s.version = '0.1.2'
s.version = '0.2.0'
s.summary = 'Services oriented AppDelegate in Swift 3.'
s.description = <<-DESC
PluggableApplicationDelegate is a way of decoupling AppDelegate, by splitting it into small modules called ApplicationService.
@@ -18,118 +18,132 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
public var window: UIWindow?
open var services: [ApplicationService] { return [] }
private lazy var __services: [ApplicationService]! = {
private lazy var __services: [ApplicationService] = {
return self.services
}()
@available(iOS 2.0, *)
public func applicationDidFinishLaunching(_ application: UIApplication) {
@discardableResult
private func apply<T, S>(_ work: (ApplicationService, @escaping (T) -> Void) -> S?, completionHandler: @escaping ([T]) -> Swift.Void) -> [S] {
let dispatchGroup = DispatchGroup()
var results: [T] = []
var returns: [S] = []
for service in __services {
service.applicationDidFinishLaunching?(application)
dispatchGroup.enter()
let returned = work(service, { result in
results.append(result)
dispatchGroup.leave()
})
if let returned = returned {
returns.append(returned)
} else { // delegate doesn't impliment method
dispatchGroup.leave()
}
if returned == nil {
}
}
dispatchGroup.notify(queue: .main) {
completionHandler(results)
}
return returns
}
@available(iOS 2.0, *)
open func applicationDidFinishLaunching(_ application: UIApplication) {
__services.forEach { $0.applicationDidFinishLaunching?(application) }
}
@available(iOS 6.0, *)
public func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
var result = true
open func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
var result = false
for service in __services {
if let serviceResult = service.application?(application, willFinishLaunchingWithOptions: launchOptions) {
if serviceResult == false {
result = false
}
if service.application?(application, willFinishLaunchingWithOptions: launchOptions) ?? false {
result = true
}
}
return result
}
@available(iOS 3.0, *)
public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
var result = true
open func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
var result = false
for service in __services {
if let serviceResult = service.application?(application, didFinishLaunchingWithOptions: launchOptions) {
if serviceResult == false {
result = false
}
if service.application?(application, didFinishLaunchingWithOptions: launchOptions) ?? false {
result = true
}
}
return true
return result
}
@available(iOS 2.0, *)
public func applicationDidBecomeActive(_ application: UIApplication) {
open func applicationDidBecomeActive(_ application: UIApplication) {
for service in __services {
service.applicationDidBecomeActive?(application)
}
}
@available(iOS 2.0, *)
public func applicationWillResignActive(_ application: UIApplication) {
open func applicationWillResignActive(_ application: UIApplication) {
for service in __services {
service.applicationWillResignActive?(application)
}
}
@available(iOS, introduced: 2.0, deprecated: 9.0, message: "Please use application:openURL:options:")
public func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
var result = true
open func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
var result = false
for service in __services {
if service.application?(application, handleOpen: url) == false {
result = false
if service.application?(application, handleOpen: url) ?? false {
result = true
}
}
return true
return result
}
@available(iOS, introduced: 4.2, deprecated: 9.0, message: "Please use application:openURL:options:")
public func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
var result = true
open func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
var result = false
for service in __services {
if service.application?(application, open: url, sourceApplication: sourceApplication, annotation: annotation) == false {
result = false
if service.application?(application, open: url, sourceApplication: sourceApplication, annotation: annotation) ?? false {
result = true
}
}
return true
return result
}
@available(iOS 9.0, *)
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
var result = true
open func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
var result = false
for service in __services {
if service.application?(app, open: url, options: options) == false {
result = false
if service.application?(app, open: url, options: options) ?? false {
result = true
}
}
return result
}
@available(iOS 2.0, *)
public func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
open func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
for service in __services {
service.applicationDidReceiveMemoryWarning?(application)
}
}
@available(iOS 2.0, *)
public func applicationWillTerminate(_ application: UIApplication) {
open func applicationWillTerminate(_ application: UIApplication) {
for service in __services {
service.applicationWillTerminate?(application)
}
}
@available(iOS 2.0, *)
public func applicationSignificantTimeChange(_ application: UIApplication) {
open func applicationSignificantTimeChange(_ application: UIApplication) {
for service in __services {
service.applicationSignificantTimeChange?(application)
}
@@ -137,26 +151,26 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS 2.0, *)
public func application(_ application: UIApplication, willChangeStatusBarOrientation newStatusBarOrientation: UIInterfaceOrientation, duration: TimeInterval) {
open func application(_ application: UIApplication, willChangeStatusBarOrientation newStatusBarOrientation: UIInterfaceOrientation, duration: TimeInterval) {
for service in __services {
service.application?(application, willChangeStatusBarOrientation: newStatusBarOrientation, duration: duration)
}
}
@available(iOS 2.0, *)
public func application(_ application: UIApplication, didChangeStatusBarOrientation oldStatusBarOrientation: UIInterfaceOrientation) {
open func application(_ application: UIApplication, didChangeStatusBarOrientation oldStatusBarOrientation: UIInterfaceOrientation) {
for service in __services {
service.application?(application, didChangeStatusBarOrientation: oldStatusBarOrientation)
}
}
// public func application(_ application: UIApplication, willChangeStatusBarFrame newStatusBarFrame: CGRect) {
// open func application(_ application: UIApplication, willChangeStatusBarFrame newStatusBarFrame: CGRect) {
// for service in __services {
// service.application?(application, willChangeStatusBarFrame: newStatusBarFrame)
// }
// }
//
// public func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) {
// open func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) {
// for service in __services {
// service.application?(application, didChangeStatusBarFrame: oldStatusBarFrame)
// }
@@ -165,7 +179,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// This callback will be made upon calling -[UIApplication registerUserNotificationSettings:]. The settings the user has granted to the application will be passed in as the second argument.
@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotification UNNotification Settings instead")
public func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
open func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
for service in __services {
service.application?(application, didRegister: notificationSettings)
}
@@ -173,7 +187,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS 3.0, *)
public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
open func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
for service in __services {
service.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}
@@ -181,7 +195,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS 3.0, *)
public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
open func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
for service in __services {
service.application?(application, didFailToRegisterForRemoteNotificationsWithError: error)
}
@@ -189,7 +203,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS, introduced: 3.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:] for user visible notifications and -[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] for silent remote notifications")
public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
open func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
for service in __services {
service.application?(application, didReceiveRemoteNotification: userInfo)
}
@@ -197,7 +211,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS, introduced: 4.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]")
public func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
open func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
for service in __services {
service.application?(application, didReceive: notification)
}
@@ -208,20 +222,22 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// A nil action identifier indicates the default action.
// You should call the completion handler as soon as you've finished handling the action.
@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]")
public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Swift.Void) {
for service in __services {
service.application?(application, handleActionWithIdentifier: identifier, for: notification, completionHandler: completionHandler)
}
open func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Swift.Void) {
apply({ (service, completion) -> Void? in
service.application?(application, handleActionWithIdentifier: identifier, for: notification, completionHandler: completion)
}, completionHandler: { _ in
completionHandler()
})
}
@available(iOS, introduced: 9.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]")
public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, handleActionWithIdentifier: identifier, forRemoteNotification: userInfo, withResponseInfo: responseInfo, completionHandler: completionHandler)
}
}, completionHandler: { _ in
completionHandler()
})
}
@@ -229,18 +245,22 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// A nil action identifier indicates the default action.
// You should call the completion handler as soon as you've finished handling the action.
@available(iOS, introduced: 8.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]")
public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, handleActionWithIdentifier: identifier, forRemoteNotification: userInfo, completionHandler: completionHandler)
}
}, completionHandler: { _ in
completionHandler()
})
}
@available(iOS, introduced: 9.0, deprecated: 10.0, message: "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]")
public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, handleActionWithIdentifier: identifier, for: notification, withResponseInfo: responseInfo, completionHandler: completionHandler)
}
}, completionHandler: { _ in
completionHandler()
})
}
@@ -248,29 +268,39 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
This method will be invoked even if the application was launched or resumed because of the remote notification. The respective delegate methods will be invoked first. Note that this behavior is in contrast to application:didReceiveRemoteNotification:, which is not called in those cases, and which will not be invoked if this method is implemented. !*/
@available(iOS 7.0, *)
public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
}
}, completionHandler: { results in
let result = results.min(by: { $0.rawValue < $1.rawValue }) ?? .noData
completionHandler(result)
})
}
/// Applications with the "fetch" background mode may be given opportunities to fetch updated content in the background or when it is convenient for the system. This method will be called in these situations. You should call the fetchCompletionHandler as soon as you're finished performing that operation, so the system can accurately estimate its power and data cost.
@available(iOS 7.0, *)
public func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, performFetchWithCompletionHandler: completionHandler)
}
}, completionHandler: { results in
let result = results.min(by: { $0.rawValue < $1.rawValue }) ?? .noData
completionHandler(result)
})
}
// Called when the user activates your application by selecting a shortcut on the home screen,
// except when -application:willFinishLaunchingWithOptions: or -application:didFinishLaunchingWithOptions returns NO.
@available(iOS 9.0, *)
public func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, performActionFor: shortcutItem, completionHandler: completionHandler)
}
}, completionHandler: { results in
// if any service handled the shortcut, return true
let result = results.reduce(false, { $0 || $1 })
completionHandler(result)
})
}
@@ -280,23 +310,37 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// callbacks. If such a session has already been created (if the app is being resumed, for instance), then the delegate will start receiving
// callbacks without any action by the application. You should call the completionHandler as soon as you're finished handling the callbacks.
@available(iOS 7.0, *)
public func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Swift.Void) {
for service in __services {
open func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Swift.Void) {
apply({ (service, completionHandler) -> Void? in
service.application?(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)
}
}, completionHandler: { _ in
completionHandler()
})
}
@available(iOS 8.2, *)
public func application(_ application: UIApplication, handleWatchKitExtensionRequest userInfo: [AnyHashable : Any]?, reply: @escaping ([AnyHashable : Any]?) -> Swift.Void) {
open func application(_ application: UIApplication, handleWatchKitExtensionRequest userInfo: [AnyHashable : Any]?, reply: @escaping ([AnyHashable : Any]?) -> Swift.Void) {
for service in __services {
service.application?(application, handleWatchKitExtensionRequest: userInfo, reply: reply)
}
apply({ (service, reply) -> Void? in
service.application?(application, handleWatchKitExtensionRequest: userInfo, reply: reply)
}, completionHandler: { results in
let result = results.reduce([:], { initial, next in
var initial = initial
for (key, value) in next ?? [:] {
initial[key] = value
}
return initial
})
reply(result)
})
}
@available(iOS 9.0, *)
public func applicationShouldRequestHealthAuthorization(_ application: UIApplication) {
open func applicationShouldRequestHealthAuthorization(_ application: UIApplication) {
for service in __services {
service.applicationShouldRequestHealthAuthorization?(application)
}
@@ -304,14 +348,14 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS 4.0, *)
public func applicationDidEnterBackground(_ application: UIApplication) {
open func applicationDidEnterBackground(_ application: UIApplication) {
for service in __services {
service.applicationDidEnterBackground?(application)
}
}
@available(iOS 4.0, *)
public func applicationWillEnterForeground(_ application: UIApplication) {
open func applicationWillEnterForeground(_ application: UIApplication) {
for service in __services {
service.applicationWillEnterForeground?(application)
}
@@ -319,14 +363,14 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
@available(iOS 4.0, *)
public func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
open func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
for service in __services {
service.applicationProtectedDataWillBecomeUnavailable?(application)
}
}
@available(iOS 4.0, *)
public func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
open func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
for service in __services {
service.applicationProtectedDataDidBecomeAvailable?(application)
}
@@ -337,21 +381,19 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// Constants representing common extension point identifiers are provided further down.
// If unimplemented, the default behavior is to allow the extension point identifier.
@available(iOS 8.0, *)
public func application(_ application: UIApplication, shouldAllowExtensionPointIdentifier extensionPointIdentifier: UIApplicationExtensionPointIdentifier) -> Bool {
var result = true
open func application(_ application: UIApplication, shouldAllowExtensionPointIdentifier extensionPointIdentifier: UIApplicationExtensionPointIdentifier) -> Bool {
var result = false
for service in __services {
if service.application?(application, shouldAllowExtensionPointIdentifier: extensionPointIdentifier) == false {
result = false
if service.application?(application, shouldAllowExtensionPointIdentifier: extensionPointIdentifier) ?? true {
result = true
}
}
return result
}
@available(iOS 6.0, *)
public func application(_ application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [Any], coder: NSCoder) -> UIViewController? {
open func application(_ application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [Any], coder: NSCoder) -> UIViewController? {
for service in __services {
if let viewController = service.application?(application, viewControllerWithRestorationIdentifierPath: identifierComponents, coder: coder) {
return viewController
@@ -362,40 +404,36 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
}
@available(iOS 6.0, *)
public func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
open func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
var result = false
for service in __services {
if service.application?(application, shouldSaveApplicationState: coder) == true {
if service.application?(application, shouldSaveApplicationState: coder) ?? false {
result = true
}
}
return result
}
@available(iOS 6.0, *)
public func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
open func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
var result = false
for service in __services {
if service.application?(application, shouldRestoreApplicationState: coder) == true {
if service.application?(application, shouldRestoreApplicationState: coder) ?? false {
result = true
}
}
return result
}
@available(iOS 6.0, *)
public func application(_ application: UIApplication, willEncodeRestorableStateWith coder: NSCoder) {
open func application(_ application: UIApplication, willEncodeRestorableStateWith coder: NSCoder) {
for service in __services {
service.application?(application, willEncodeRestorableStateWith: coder)
}
}
@available(iOS 6.0, *)
public func application(_ application: UIApplication, didDecodeRestorableStateWith coder: NSCoder) {
open func application(_ application: UIApplication, didDecodeRestorableStateWith coder: NSCoder) {
for service in __services {
service.application?(application, didDecodeRestorableStateWith: coder)
}
@@ -407,15 +445,13 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// For each application:willContinueUserActivityWithType: invocation, you are guaranteed to get exactly one invocation of application:continueUserActivity: on success,
// or application:didFailToContinueUserActivityWithType:error: if an error was encountered.
@available(iOS 8.0, *)
public func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
open func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
var result = false
for service in __services {
if service.application?(application, willContinueUserActivityWithType: userActivityType) == true {
if service.application?(application, willContinueUserActivityWithType: userActivityType) ?? false {
result = true
}
}
return result
}
@@ -425,22 +461,21 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// invoked with the user activity. Invoking the restorationHandler is optional. It may be copied and invoked later, and it will bounce to the main thread to complete its work and call
// restoreUserActivityState on all objects.
@available(iOS 8.0, *)
public func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Swift.Void) -> Bool {
var result = false
open func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Swift.Void) -> Bool {
let returns = apply({ (service, restorationHandler) -> Bool? in
service.application?(application, continue: userActivity, restorationHandler: restorationHandler)
}, completionHandler: { results in
let result = results.reduce([], { $0 + ($1 ?? []) })
restorationHandler(result)
})
for service in __services {
if service.application?(application, continue: userActivity, restorationHandler: restorationHandler) == true {
result = false
}
}
return result
return returns.reduce(false, { $0 || $1 })
}
// If the user activity cannot be fetched after willContinueUserActivityWithType is called, this will be called on the main thread when implemented.
@available(iOS 8.0, *)
public func application(_ application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: Error) {
open func application(_ application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: Error) {
for service in __services {
service.application?(application, didFailToContinueUserActivityWithType: userActivityType, error: error)
}
@@ -449,7 +484,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// This is called on the main thread when a user activity managed by UIKit has been updated. You can use this as a last chance to add additional data to the userActivity.
@available(iOS 8.0, *)
public func application(_ application: UIApplication, didUpdate userActivity: NSUserActivity) {
open func application(_ application: UIApplication, didUpdate userActivity: NSUserActivity) {
for service in __services {
service.application?(application, didUpdate: userActivity)
}
@@ -460,7 +495,7 @@ open class PluggableApplicationDelegate: UIResponder, UIApplicationDelegate {
// You should use the CKShareMetadata object's shareURL and containerIdentifier to schedule a CKAcceptSharesOperation, then start using
// the resulting CKShare and its associated record(s), which will appear in the CKContainer's shared database in a zone matching that of the record's owner.
@available(iOS 10.0, *)
public func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {
open func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {
for service in __services {
service.application?(application, userDidAcceptCloudKitShareWith: cloudKitShareMetadata)
}
+1 -1
View File
@@ -72,7 +72,7 @@ PluggableApplicationDelegate is available through [CocoaPods](http://cocoapods.o
it, simply add the following line to your Podfile:
```ruby
pod "PluggableApplicationDelegate", :git => "https://github.com/fmo91/PluggableApplicationDelegate"
pod 'PluggableApplicationDelegate'
```
## Author