diff --git a/.swift-version b/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/.travis.yml b/.travis.yml index f0ba2a2..1c271be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: objective-c -osx_image: xcode7.3 +osx_image: xcode8 before_script: - bundle install script: - - xctool -project SuperDelegate.xcodeproj -scheme SuperDelegate -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPad Air 2" test - - xctool -project Sample/SampleDelegate/SampleDelegate.xcodeproj -scheme SampleDelegate -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPad Air 2" build + - xcodebuild -project SuperDelegate.xcodeproj -scheme SuperDelegate -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone SE" test + - xcodebuild -project Sample/SampleDelegate/SampleDelegate.xcodeproj -scheme SampleDelegate -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone SE" build - pod lib lint --verbose --fail-fast diff --git a/Gemfile b/Gemfile index 65c5c04..1b92058 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,3 @@ source 'https://rubygems.org' do - gem 'cocoapods', '1.0.0' - gem 'activesupport', '~> 4.0' + gem 'cocoapods', '1.1.0.rc.2' end diff --git a/README.md b/README.md index 1653d89..4265901 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,8 @@ To opt into more AppDelegate features, have your `AppDelegate` class conform to ## Versions * 0.8.* – Swift 2.3 and Xcode 7.3+. This version has been thouroughly vetted. -* 0.9.* – Swift 3.0 and Beta Xcode 8. This version is in active development. -* 1.0 – Will be released when iOS 10 is near release. +* 0.9.* – Swift 3.0 and Xcode 8+. +* 1.0 – Swift 3.0, Xcode 8+, and iOS 10 SDK adoption. ## Contributing diff --git a/Sample/SampleDelegate/SampleDelegate.xcodeproj/project.pbxproj b/Sample/SampleDelegate/SampleDelegate.xcodeproj/project.pbxproj index 48e1b93..ea1af0a 100644 --- a/Sample/SampleDelegate/SampleDelegate.xcodeproj/project.pbxproj +++ b/Sample/SampleDelegate/SampleDelegate.xcodeproj/project.pbxproj @@ -7,15 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - EAB6215D1D877D930087F1D3 /* SuperDelegate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAECD1BB1D0CAC07008BB9F5 /* SuperDelegate.framework */; }; - EAB6215E1D877D930087F1D3 /* SuperDelegate.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EAECD1BB1D0CAC07008BB9F5 /* SuperDelegate.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + EAEA845E1D8A1C0200F63F90 /* SuperDelegate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAECD1BB1D0CAC07008BB9F5 /* SuperDelegate.framework */; }; + EAEA845F1D8A1C0200F63F90 /* SuperDelegate.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EAECD1BB1D0CAC07008BB9F5 /* SuperDelegate.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; EAECD1A41D0CABFD008BB9F5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAECD1A31D0CABFD008BB9F5 /* AppDelegate.swift */; }; EAECD1A61D0CABFD008BB9F5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAECD1A51D0CABFD008BB9F5 /* ViewController.swift */; }; EAECD1AB1D0CABFD008BB9F5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAECD1AA1D0CABFD008BB9F5 /* Assets.xcassets */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - EAB6215F1D877D930087F1D3 /* PBXContainerItemProxy */ = { + EAEA84601D8A1C0200F63F90 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = EAECD1B51D0CAC07008BB9F5 /* SuperDelegate.xcodeproj */; proxyType = 1; @@ -39,13 +39,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - EAB621611D877D930087F1D3 /* Embed Frameworks */ = { + EAEA84621D8A1C0200F63F90 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - EAB6215E1D877D930087F1D3 /* SuperDelegate.framework in Embed Frameworks */, + EAEA845F1D8A1C0200F63F90 /* SuperDelegate.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -66,7 +66,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EAB6215D1D877D930087F1D3 /* SuperDelegate.framework in Frameworks */, + EAEA845E1D8A1C0200F63F90 /* SuperDelegate.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -120,12 +120,12 @@ EAECD19C1D0CABFD008BB9F5 /* Sources */, EAECD19D1D0CABFD008BB9F5 /* Frameworks */, EAECD19E1D0CABFD008BB9F5 /* Resources */, - EAB621611D877D930087F1D3 /* Embed Frameworks */, + EAEA84621D8A1C0200F63F90 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( - EAB621601D877D930087F1D3 /* PBXTargetDependency */, + EAEA84611D8A1C0200F63F90 /* PBXTargetDependency */, ); name = SampleDelegate; productName = SampleDelegate; @@ -139,11 +139,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Square, Inc."; TargetAttributes = { EAECD19F1D0CABFD008BB9F5 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; }; }; }; @@ -212,10 +213,10 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - EAB621601D877D930087F1D3 /* PBXTargetDependency */ = { + EAEA84611D8A1C0200F63F90 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SuperDelegate; - targetProxy = EAB6215F1D877D930087F1D3 /* PBXContainerItemProxy */; + targetProxy = EAEA84601D8A1C0200F63F90 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -234,8 +235,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -262,6 +265,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -279,8 +283,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -299,6 +305,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_VERSION = 3.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -306,24 +313,27 @@ EAECD1B31D0CABFD008BB9F5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; INFOPLIST_FILE = SampleDelegate/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SampleDelegate; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; EAECD1B41D0CABFD008BB9F5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; INFOPLIST_FILE = SampleDelegate/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SampleDelegate; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Sample/SampleDelegate/SampleDelegate.xcodeproj/xcshareddata/xcschemes/SampleDelegate.xcscheme b/Sample/SampleDelegate/SampleDelegate.xcodeproj/xcshareddata/xcschemes/SampleDelegate.xcscheme index b587904..d6c960f 100644 --- a/Sample/SampleDelegate/SampleDelegate.xcodeproj/xcshareddata/xcschemes/SampleDelegate.xcscheme +++ b/Sample/SampleDelegate/SampleDelegate.xcodeproj/xcshareddata/xcschemes/SampleDelegate.xcscheme @@ -1,6 +1,6 @@ Void)) { - switch notificationOrigin { - case .UserTappedToBringAppToForeground: + func didReceive(remoteNotification: RemoteNotification, origin: UserNotificationOrigin, fetchCompletionHandler completionHandler: (@escaping (UIBackgroundFetchResult) -> Void)) { + switch origin { + case .userTappedToBringAppToForeground: // The customer tapped on the notification. Show UI about the notification. break - case .DeliveredWhileInForground: + case .deliveredWhileInForeground: // The customer has not seen this notification. Alert the customer somehow. break - case .DeliveredWhileInBackground: + case .deliveredWhileInBackground: // Process the background notification. break } @@ -100,62 +100,62 @@ extension AppDelegate: RemoteNotificationCapable { extension AppDelegate: UserNotificationCapable { func requestedUserNotificationSettings() -> UIUserNotificationSettings { - return UIUserNotificationSettings(forTypes: [.Badge, .Sound, .Alert], categories: nil) + return UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil) } - func didReceiveUserNotificationPermissions(userNotificationPermissionsGranted: UserNotificationPermissionsGranted) { - switch userNotificationPermissionsGranted { - case .None: + func didReceive(userNotificationPermissions: UserNotificationPermissionsGranted) { + switch userNotificationPermissions { + case .none: // The customer has denied user (e.g. local and loud remote) notification permissions. break - case .Requested: + case .requested: // The customer has given us permission for all requested user notifications. break - case let .Some(grantedPermissions): - print("Customer refused to give us permissions for \(requestedUserNotificationSettings().types.exclusiveOr(grantedPermissions))") + case let .partial(grantedPermissions): + print("Customer refused to give us permissions for \(requestedUserNotificationSettings().types.symmetricDifference(grantedPermissions))") break } } } extension AppDelegate: LocalNotificationCapable { - func didReceiveLocalNotification(localNotification: UILocalNotification, notificationOrigin: UserNotificationOrigin) { + func didReceive(localNotification: UILocalNotification, origin: UserNotificationOrigin) { // Process the notification. } } extension AppDelegate: OpenURLCapable { - func canOpenLaunchURL(launchURLToOpen: URLToOpen) -> Bool { + func canOpen(launchURL: URLToOpen) -> Bool { // SampleDelegate can handle all URLs given to us at launch! If some URLs shouldn't open your app, return false here. return true } - func handleURLToOpen(urlToOpen: URLToOpen) -> Bool { + func handle(urlToOpen: URLToOpen) -> Bool { // Show UI that corresponds to the opened URL. If you can't open the URL, return false here. return true } } extension AppDelegate: ShortcutCapable { - func canHandleShortcutItem(shortcutItem: UIApplicationShortcutItem) -> Bool { + func canHandle(shortcutItem: UIApplicationShortcutItem) -> Bool { // SampleDelegate can handle all shortcut items! If your app needs to invalidate shortcut items that were set by a previous version of the app, return false here. return true } - func handleShortcutItem(shortcutItem: UIApplicationShortcutItem, completionHandler: () -> Void) { + func handle(shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping () -> Void) { // Process the shortcut, then tell iOS that we've handled the shortcut. completionHandler() } } extension AppDelegate: UserActivityCapable { - func canHandleUserActivity(userActivity: NSUserActivity) -> Bool { + func canResume(userActivity: NSUserActivity) -> Bool { // SampleDelegate can handle all user activity items! return true } - func continueUserActivity(userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool { + func resume(userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { // Show UI for the user activity. return true } -} \ No newline at end of file +} diff --git a/Sample/SampleDelegate/SampleDelegate/ViewController.swift b/Sample/SampleDelegate/SampleDelegate/ViewController.swift index 344c2dd..4f63bac 100644 --- a/Sample/SampleDelegate/SampleDelegate/ViewController.swift +++ b/Sample/SampleDelegate/SampleDelegate/ViewController.swift @@ -26,7 +26,7 @@ class ViewController: UIViewController { super.viewDidLoad() // Show that our view has been loaded by changing our background color to blue. - view.backgroundColor = UIColor.blueColor() + view.backgroundColor = UIColor.blue } } diff --git a/Sources/LaunchItem.swift b/Sources/LaunchItem.swift index 027af9e..ef3c7f4 100644 --- a/Sources/LaunchItem.swift +++ b/Sources/LaunchItem.swift @@ -22,34 +22,59 @@ import Foundation public enum LaunchItem: CustomStringConvertible, Equatable { - case RemoteNotificationItem(remoteNotification: RemoteNotification) - case LocalNotificationItem(localNotification: UILocalNotification) - case OpenURLItem(urlToOpen: URLToOpen) + case remoteNotification(item: RemoteNotification) + case localNotification(item: UILocalNotification) + case openURL(item: URLToOpen) @available(iOS 9.0, *) - case ShortcutItem(shortcutItem: UIApplicationShortcutItem) - case UserActivityItem(userActivity: NSUserActivity) - case NoItem + case shortcut(item: UIApplicationShortcutItem) + case userActivity(item: NSUserActivity) + case none + + // MARK: Equatable + + public static func ==(lhs: LaunchItem, rhs: LaunchItem) -> Bool { + switch (lhs, rhs) { + case let (.remoteNotification(itemLHS), .remoteNotification(itemRHS)) where itemLHS == itemRHS: + return true + case let (.localNotification(itemLHS), .localNotification(itemRHS)) where itemLHS == itemRHS: + return true + case let (.openURL(itemLHS), .openURL(itemRHS)) where itemLHS == itemRHS: + return true + case let (.shortcut(itemLHS), .shortcut(itemRHS)) where itemLHS == itemRHS: + return true + case let (.userActivity(itemLHS), .userActivity(itemRHS)) where itemLHS == itemRHS: + return true + case (.none, .none): + return true + default: + return false + } + } // MARK: Initialization - init(launchOptions: [NSObject : AnyObject]?) { - if let launchRemoteNotification = RemoteNotification(remoteNotification: launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject : AnyObject]) { - self = .RemoteNotificationItem(remoteNotification: launchRemoteNotification) - } else if let launchLocalNotification = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification { - self = .LocalNotificationItem(localNotification: launchLocalNotification) - } else if let launchURL = launchOptions?[UIApplicationLaunchOptionsURLKey] as? NSURL { - let sourceApplicationBundleID = launchOptions?[UIApplicationLaunchOptionsSourceApplicationKey] as? String - let annotation = launchOptions?[UIApplicationLaunchOptionsAnnotationKey] + init(launchOptions: [AnyHashable : Any]?) { + if let launchRemoteNotification = RemoteNotification(remoteNotification: launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable : Any]) { + self = .remoteNotification(item: launchRemoteNotification) + + } else if let launchLocalNotification = launchOptions?[UIApplicationLaunchOptionsKey.localNotification] as? UILocalNotification { + self = .localNotification(item: launchLocalNotification) + + } else if let launchURL = launchOptions?[UIApplicationLaunchOptionsKey.url] as? URL { + let sourceApplicationBundleID = launchOptions?[UIApplicationLaunchOptionsKey.sourceApplication] as? String + let annotation = launchOptions?[UIApplicationLaunchOptionsKey.annotation] + if #available(iOS 9.0, *) { - self = OpenURLItem(urlToOpen: URLToOpen( + self = .openURL(item: URLToOpen( url: launchURL, sourceApplicationBundleID: sourceApplicationBundleID, annotation: annotation, - copyBeforeUse: launchOptions?[UIApplicationOpenURLOptionsOpenInPlaceKey] as? Bool ?? false + copyBeforeUse: launchOptions?[UIApplicationLaunchOptionsKey.openInPlace] as? Bool ?? false ) ) + } else { - self = OpenURLItem(urlToOpen: URLToOpen( + self = .openURL(item: URLToOpen( url: launchURL, sourceApplicationBundleID: sourceApplicationBundleID, annotation: annotation, @@ -57,13 +82,16 @@ public enum LaunchItem: CustomStringConvertible, Equatable { ) ) } - } else if #available(iOS 9.0, *), let launchShortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem { - self = .ShortcutItem(shortcutItem: launchShortcutItem) - } else if let launchUserActivity = (launchOptions?[UIApplicationLaunchOptionsUserActivityDictionaryKey] as? [String : AnyObject])?[ApplicationLaunchOptionsUserActivityKey] as? NSUserActivity { - // Unfortunately, "UIApplicationLaunchOptionsUserActivityKey" has no constant, but it is there. - self = .UserActivityItem(userActivity: launchUserActivity) + + } else if #available(iOS 9.0, *), let launchShortcutItem = launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem { + self = .shortcut(item: launchShortcutItem) + + } else if let userActivityDictionary = launchOptions?[UIApplicationLaunchOptionsKey.userActivityDictionary] as? [UIApplicationLaunchOptionsKey : Any], + let launchUserActivity = userActivityDictionary[UIApplicationLaunchOptionsKey.userActivity] as? NSUserActivity { + self = .userActivity(item: launchUserActivity) + } else { - self = .NoItem + self = .none } } @@ -72,101 +100,75 @@ public enum LaunchItem: CustomStringConvertible, Equatable { public var description: String { // Creating a custom string for LaunchItem to prevent a crash when printing any enum values with associated items on iOS 8. Swift accesses the class of every possible associated object when printing an enum instance with an asssociated value, no matter which case the instance represents. This causes a crash on iOS 8 since swift attempts to access UIApplicationShortcutItem, which doesn't exist on iOS 8. Filed rdar://26699861 – hoping for a fix in Swift 3. switch self { - case let .RemoteNotificationItem(remoteNotification): - return "LaunchItem.RemoteNotificationItem: \(remoteNotification)" - case let .LocalNotificationItem(localNotification): - return "LaunchItem.LocalNotificationItem: \(localNotification)" - case let .OpenURLItem(urlToOpen): - return "LaunchItem.OpenURLItem: \(urlToOpen)" - case let .ShortcutItem(shortcutItem): - return "LaunchItem.ShortcutItem: \(shortcutItem)" - case let .UserActivityItem(userActivity): - return "LaunchItem.UserActivityItem: \(userActivity)" - case .NoItem: - return "LaunchItem.NoItem" + case let .remoteNotification(item): + return "LaunchItem.remoteNotification: \(item)" + case let .localNotification(item): + return "LaunchItem.localNotification: \(item)" + case let .openURL(item): + return "LaunchItem.openURL: \(item)" + case let .shortcut(item): + return "LaunchItem.shortcut: \(item)" + case let .userActivity(item): + return "LaunchItem.userActivity: \(item)" + case .none: + return "LaunchItem.none" } } // MARK: Public Properties /// The launch options that were used to construct the enum, for passing into third party APIs. - public var launchOptions: [NSObject : AnyObject] { - get { - switch self { - case let .RemoteNotificationItem(remoteNotification): - return [ - UIApplicationLaunchOptionsRemoteNotificationKey : remoteNotification.remoteNotificationDictionary - ] - - case let .LocalNotificationItem(localNotification): - return [ - UIApplicationLaunchOptionsLocalNotificationKey : localNotification - ] - - case let OpenURLItem(urlToOpen): - var launchOptions: [NSObject : AnyObject] = [ - UIApplicationLaunchOptionsURLKey : urlToOpen.url - ] - - if let sourceApplicationBundleID = urlToOpen.sourceApplicationBundleID { - launchOptions[UIApplicationLaunchOptionsSourceApplicationKey] = sourceApplicationBundleID - } - - if let annotation = urlToOpen.annotation { - launchOptions[UIApplicationLaunchOptionsAnnotationKey] = annotation - } - - if #available(iOS 9.0, *) { - launchOptions[UIApplicationOpenURLOptionsOpenInPlaceKey] = urlToOpen.copyBeforeUse - } - - return launchOptions - - case let ShortcutItem(shortcutItem): - if #available(iOS 9.0, *) { - return [ - UIApplicationLaunchOptionsShortcutItemKey : shortcutItem - ] - } else { - // If we are a .ShortcutItem and we are not on iOS 9 or later, something absolutely terrible has happened. - fatalError() - } - - case let UserActivityItem(userActivity): + public var launchOptions: [AnyHashable : Any] { + switch self { + case let .remoteNotification(item): + return [ + UIApplicationLaunchOptionsKey.remoteNotification : item.remoteNotificationDictionary + ] + + case let .localNotification(item): + return [ + UIApplicationLaunchOptionsKey.localNotification : item + ] + + case let .openURL(item): + var launchOptions: [AnyHashable : Any] = [ + UIApplicationLaunchOptionsKey.url : item.url + ] + + if let sourceApplicationBundleID = item.sourceApplicationBundleID { + launchOptions[UIApplicationLaunchOptionsKey.sourceApplication] = sourceApplicationBundleID + } + + if let annotation = item.annotation { + launchOptions[UIApplicationLaunchOptionsKey.annotation] = annotation + } + + if #available(iOS 9.0, *) { + launchOptions[UIApplicationLaunchOptionsKey.openInPlace] = item.copyBeforeUse + } + + return launchOptions + + case let .shortcut(item): + if #available(iOS 9.0, *) { return [ - UIApplicationLaunchOptionsUserActivityDictionaryKey : [ - UIApplicationLaunchOptionsUserActivityTypeKey : userActivity.activityType, - ApplicationLaunchOptionsUserActivityKey : userActivity - ] + UIApplicationLaunchOptionsKey.shortcutItem : item ] - - case NoItem: - return [:] + } else { + // If we are a .shortcut and we are not on iOS 9 or later, something absolutely terrible has happened. + fatalError() } + + case let .userActivity(item): + return [ + UIApplicationLaunchOptionsKey.userActivityDictionary : [ + UIApplicationLaunchOptionsKey.userActivityType : item.activityType, + UIApplicationLaunchOptionsKey.userActivity : item + ] + ] + + case .none: + return [:] } } } - - -// MARK: Equatable - - -@warn_unused_result -public func ==(lhs: LaunchItem, rhs: LaunchItem) -> Bool { - switch (lhs, rhs) { - case let (.RemoteNotificationItem(remoteNotifLHS), .RemoteNotificationItem(remoteNotifRHS)) where remoteNotifLHS == remoteNotifRHS: - return true - case let (.LocalNotificationItem(localNotifLHS), .LocalNotificationItem(localNotifRHS)) where localNotifLHS == localNotifRHS: - return true - case let (.OpenURLItem(urlLHS), .OpenURLItem(urlRHS)) where urlLHS == urlRHS: - return true - case let (.ShortcutItem(shortcutItemLHS), .ShortcutItem(shortcutItemRHS)) where shortcutItemLHS == shortcutItemRHS: - return true - case let (.UserActivityItem(userActivityTypeLHS), .UserActivityItem(userActivityTypeRHS)) where userActivityTypeLHS == userActivityTypeRHS: - return true - case (.NoItem, .NoItem): - return true - default: - return false - } -} diff --git a/Sources/RemoteNotification.swift b/Sources/RemoteNotification.swift index 7fdec6e..0952406 100644 --- a/Sources/RemoteNotification.swift +++ b/Sources/RemoteNotification.swift @@ -33,12 +33,23 @@ public struct RemoteNotification: CustomStringConvertible, Equatable { /// The identifier for the UIUserNotificationCategory associated with the push notification. Derived from userInfo["category"] public let categoryIdentifier: String? /// Custom fields on the remote notification. - public let userInfo: [String : AnyObject] + public let userInfo: [String : Any] /// The dictionary representation of the remote notification. - public let remoteNotificationDictionary: [String : AnyObject] + public let remoteNotificationDictionary: [String : Any] - public init?(remoteNotification: [NSObject : AnyObject]?) { - guard let remoteNotification = remoteNotification as? [String : AnyObject] else { + // MARK: Equatable + + public static func ==(lhs: RemoteNotification, rhs: RemoteNotification) -> Bool { + return lhs.alert == rhs.alert + && lhs.badge == rhs.badge + && lhs.sound == rhs.sound + && lhs.contentAvailable == rhs.contentAvailable + && lhs.categoryIdentifier == rhs.categoryIdentifier + && NSDictionary(dictionary: lhs.userInfo) == NSDictionary(dictionary: rhs.userInfo) + } + + public init?(remoteNotification: [AnyHashable : Any]?) { + guard let remoteNotification = remoteNotification as? [String : Any] else { return nil } @@ -46,7 +57,7 @@ public struct RemoteNotification: CustomStringConvertible, Equatable { // See https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html for more information on expected values. alert = Alert(remoteNotification: remoteNotification) - let apnsDictionary = remoteNotification[APSServiceKey] as? [String : AnyObject] + let apnsDictionary = remoteNotification[APSServiceKey] as? [String : Any] badge = apnsDictionary?[badgeKey] as? Int sound = apnsDictionary?[soundKey] as? String contentAvailable = apnsDictionary?[contentAvailableKey] != nil @@ -54,7 +65,7 @@ public struct RemoteNotification: CustomStringConvertible, Equatable { remoteNotificationDictionary = remoteNotification var customFields = remoteNotification - customFields.removeValueForKey(APSServiceKey) + customFields.removeValue(forKey: APSServiceKey) userInfo = customFields } @@ -88,10 +99,27 @@ public struct RemoteNotification: CustomStringConvertible, Equatable { /// The localization arguments for the title shown on the Apple Watch. Derived from userInfo["aps"]["alert"]["title-loc-args"] public let wearableTitleLocalizationArguments: [String]? - init?(remoteNotification: [String : AnyObject]) { + // MARK: Equatable + + public static func ==(lhs: Alert, rhs: Alert) -> Bool { + return lhs.body == rhs.body + && lhs.bodyLocalizationKey == rhs.bodyLocalizationKey + && lhs.bodyLocalizationArguments ?? [] == rhs.bodyLocalizationArguments ?? [] + && lhs.actionLocalizationKey == rhs.actionLocalizationKey + && lhs.launchImageName == rhs.launchImageName + && lhs.wearableTitle == rhs.wearableTitle + && lhs.wearableTitleLocalizationKey == rhs.wearableTitleLocalizationKey + && lhs.wearableTitleLocalizationArguments ?? [] == rhs.wearableTitleLocalizationArguments ?? [] + } + + init?(remoteNotification: [String : Any]) { // Alert is represented as either a dictionary or a single string. - guard let alert = remoteNotification[APSServiceKey]?[alertKey] as? [String : AnyObject] else { - guard let body = remoteNotification[APSServiceKey]?[alertKey] as? String else { + guard let apnsDictionary = remoteNotification[APSServiceKey] as? [String : Any] else { + return nil + } + + guard let alert = apnsDictionary[alertKey] as? [String : Any] else { + guard let body = apnsDictionary[alertKey] as? String else { return nil } @@ -124,99 +152,6 @@ public struct RemoteNotification: CustomStringConvertible, Equatable { } -// MARK: Equatable - -@warn_unused_result -public func ==(lhs: RemoteNotification, rhs: RemoteNotification) -> Bool { - if lhs.alert != nil || rhs.alert != nil { - guard let lhsAlert = lhs.alert, let rhsAlert = rhs.alert where lhsAlert == rhsAlert else { - return false - } - } - - if lhs.badge != nil || rhs.badge != nil { - guard let lhsBadge = lhs.badge, let rhsBadge = rhs.badge where lhsBadge == rhsBadge else { - return false - } - } - - if lhs.sound != nil || rhs.sound != nil { - guard let lhsSound = lhs.sound, let rhsSound = rhs.sound where lhsSound == rhsSound else { - return false - } - } - - guard lhs.contentAvailable == rhs.contentAvailable else { - return false - } - - if lhs.categoryIdentifier != nil || rhs.categoryIdentifier != nil { - guard let lhsCategoryIdentifier = lhs.categoryIdentifier, let rhsCategoryIdentifier = rhs.categoryIdentifier where lhsCategoryIdentifier == rhsCategoryIdentifier else { - return false - } - } - - guard NSDictionary(dictionary: lhs.userInfo) == NSDictionary(dictionary: rhs.userInfo) else { - return false - } - - return true -} - -@warn_unused_result -public func ==(lhs: RemoteNotification.Alert, rhs: RemoteNotification.Alert) -> Bool { - if lhs.body != nil || rhs.body != nil { - guard let lhsBody = lhs.body, let rhsBody = rhs.body where lhsBody == rhsBody else { - return false - } - } - - if lhs.bodyLocalizationKey != nil || rhs.bodyLocalizationKey != nil { - guard let lhsBodyLocalizationKey = lhs.bodyLocalizationKey, let rhsBodyLocalizationKey = rhs.bodyLocalizationKey where lhsBodyLocalizationKey == rhsBodyLocalizationKey else { - return false - } - } - - if lhs.bodyLocalizationArguments != nil || rhs.bodyLocalizationArguments != nil { - guard let lhsBodyLocalizationArguments = lhs.bodyLocalizationArguments, let rhsBodyLocalizationArguments = rhs.bodyLocalizationArguments where lhsBodyLocalizationArguments == rhsBodyLocalizationArguments else { - return false - } - } - - if lhs.actionLocalizationKey != nil || rhs.actionLocalizationKey != nil { - guard let lhsActionLocalizationKey = lhs.actionLocalizationKey, let rhsActionLocalizationKey = rhs.actionLocalizationKey where lhsActionLocalizationKey == rhsActionLocalizationKey else { - return false - } - } - - if lhs.launchImageName != nil || rhs.launchImageName != nil { - guard let lhsLaunchImageName = lhs.launchImageName, let rhsLaunchImageName = rhs.launchImageName where lhsLaunchImageName == rhsLaunchImageName else { - return false - } - } - - if lhs.wearableTitle != nil || rhs.wearableTitle != nil { - guard let lhsWearableTitle = lhs.wearableTitle, let rhsWearableTitle = rhs.wearableTitle where lhsWearableTitle == rhsWearableTitle else { - return false - } - } - - if lhs.wearableTitleLocalizationKey != nil || rhs.wearableTitleLocalizationKey != nil { - guard let lhsWearableTitleLocalizationKey = lhs.wearableTitleLocalizationKey, let rhsWearableTitleLocalizationKey = rhs.wearableTitleLocalizationKey where lhsWearableTitleLocalizationKey == rhsWearableTitleLocalizationKey else { - return false - } - } - - if lhs.wearableTitleLocalizationArguments != nil || rhs.wearableTitleLocalizationArguments != nil { - guard let lhsWearableTitleLocalizationArguments = lhs.wearableTitleLocalizationArguments, let rhsWearableTitleLocalizationArguments = rhs.wearableTitleLocalizationArguments where lhsWearableTitleLocalizationArguments == rhsWearableTitleLocalizationArguments else { - return false - } - } - - return true -} - - // MARK: Top Level APS Keys diff --git a/Sources/SuperDelegate+Bluetooth.swift b/Sources/SuperDelegate+Bluetooth.swift index 10b937a..2b21695 100644 --- a/Sources/SuperDelegate+Bluetooth.swift +++ b/Sources/SuperDelegate+Bluetooth.swift @@ -26,7 +26,7 @@ import Foundation public protocol BackgroundBluetoothPeripheralCapable: ApplicationLaunched { /// Called when the application is launched due to background bluetooth peripheral activity. - func restoreBluetoothPeripheralManagersWithIdentifiers(peripheralManagerIdentifiersToRestore: [String]) + func restoreBluetoothPeripheralManagers(withIdentifiers identifiers: [String]) } @@ -35,5 +35,5 @@ public protocol BackgroundBluetoothPeripheralCapable: ApplicationLaunched { public protocol BackgroundBluetoothCentralCapable: ApplicationLaunched { /// Called when the application is launched due to background bluetooth central activity. - func restoreBluetoothCentralManagersWithIdentifiers(centralManagerIdentifiersToRestore: [String]) + func restoreBluetoothCentralManagers(withIdentifiers identifiers: [String]) } diff --git a/Sources/SuperDelegate+Handoff.swift b/Sources/SuperDelegate+Handoff.swift index 92e14dd..8ea5c11 100644 --- a/Sources/SuperDelegate+Handoff.swift +++ b/Sources/SuperDelegate+Handoff.swift @@ -27,14 +27,13 @@ import Foundation public protocol HandoffCapable: UserActivityCapable { /// Called whenever your application takes responsibility for notifying users when a continuation activity takes longer than expected. Use this method to provide immediate feedback to the user that an activity is about to continue on this device. The app calls this method as soon as the user confirms that an activity should be continued but possibly before the data associated with that activity is available. /// @return true if you want to notify the user that a continuation is in progress or false if you want iOS to notify the user. - @warn_unused_result - func willContinueUserActivityWithType(userActivityType: String) -> Bool + func willContinue(userActivityType: String) -> Bool /// Called whenever a user activity item managed by UIKit has been updated. - func didUpdateUserActivity(userActivity: NSUserActivity) + func didUpdate(userActivity: NSUserActivity) /// Called whenever iOS failed to continue a user activity. - func didFailToContinueUserActivityWithType(userActivityType: String, error: NSError) + func didFailToContinue(userActivityType: String, error: Error) } @@ -47,31 +46,31 @@ extension SuperDelegate { // MARK: UIApplicationDelegate - @warn_unused_result - final public func application(application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool { + final public func application(_ application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool { guard let userActivityCapableSelf = self as? HandoffCapable else { noteImproperAPIUsage("Received willContinueUserActivityWithType but \(self) does not conform to HandoffCapable. Not handling handoff event.") return false } - return userActivityCapableSelf.willContinueUserActivityWithType(userActivityType) + return userActivityCapableSelf.willContinue(userActivityType: userActivityType) } - final public func application(application: UIApplication, didUpdateUserActivity userActivity: NSUserActivity) { + @objc(application:didUpdateUserActivity:) + final public func application(_ application: UIApplication, didUpdate userActivity: NSUserActivity) { guard let userActivityCapableSelf = self as? HandoffCapable else { noteImproperAPIUsage("Received didUpdateUserActivity but \(self) does not conform to HandoffCapable. Not handling handoff event.") return } - userActivityCapableSelf.didUpdateUserActivity(userActivity) + userActivityCapableSelf.didUpdate(userActivity: userActivity) } - final public func application(application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: NSError) { + final public func application(_ application: UIApplication, didFailToContinueUserActivityWithType userActivityType: String, error: Error) { guard let userActivityCapableSelf = self as? HandoffCapable else { noteImproperAPIUsage("Received didFailToContinueUserActivityWithType but \(self) does not conform to HandoffCapable. Not handling handoff event.") return } - userActivityCapableSelf.didFailToContinueUserActivityWithType(userActivityType, error: error) + userActivityCapableSelf.didFailToContinue(userActivityType: userActivityType, error: error) } } diff --git a/Sources/SuperDelegate+LocalNotifications.swift b/Sources/SuperDelegate+LocalNotifications.swift index 4b40e14..24f78aa 100644 --- a/Sources/SuperDelegate+LocalNotifications.swift +++ b/Sources/SuperDelegate+LocalNotifications.swift @@ -19,14 +19,15 @@ // import Foundation +import UserNotifications // MARK: LocalNotificationCapable – Opting into this protocol gives your app the ability to process local notifications. public protocol LocalNotificationCapable: UserNotificationCapable { - /// Called when your app receives a local notification. Will not be called for notifications that were delivered to the app via loadInterfaceWithLaunchItem(_:). - func didReceiveLocalNotification(localNotification: UILocalNotification, notificationOrigin: UserNotificationOrigin) + /// Called when your app receives a local notification. Will not be called for notifications that were delivered to the app via loadInterface(launchItem:). + func didReceive(localNotification: UILocalNotification, origin: UserNotificationOrigin) } @@ -35,7 +36,7 @@ public protocol LocalNotificationCapable: UserNotificationCapable { public protocol LocalNotificationActionCapable: LocalNotificationCapable { /// Called when your app has to handle a local notification action tapped by the user. Execute completionHandler when your application has handled the action to prevent iOS from killing your app. - func handleLocalNotificationActionWithIdentifier(actionIdentifier: String?, forLocalNotification notification: UILocalNotification, withResponseInfo responseInfo: [String : AnyObject]?, completionHandler: () -> Void) + func handleLocalNotification(actionIdentifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [String : Any]?, completionHandler: @escaping () -> Swift.Void) } @@ -48,7 +49,8 @@ extension SuperDelegate { // MARK: UIApplicationDelegate - final public func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) { + @objc(application:didReceiveLocalNotification:) + final public func application(_ application: UIApplication, didReceive notification: UILocalNotification) { guard let localNotificationsCapableSelf = self as? LocalNotificationCapable else { noteImproperAPIUsage("Received local notification but \(self) does not conform to LocalNotificationCapable. Ignoring.") return @@ -61,31 +63,33 @@ extension SuperDelegate { let notificationOrigin: UserNotificationOrigin if applicationIsInForeground { - notificationOrigin = .DeliveredWhileInForground + notificationOrigin = .deliveredWhileInForeground } else { - notificationOrigin = .UserTappedToBringAppToForeground + notificationOrigin = .userTappedToBringAppToForeground } - localNotificationsCapableSelf.didReceiveLocalNotification(notification, notificationOrigin: notificationOrigin) + localNotificationsCapableSelf.didReceive(localNotification: notification, origin: notificationOrigin) } - final public func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, completionHandler: () -> Void) { + @objc(application:handleActionWithIdentifier:forLocalNotification:completionHandler:) + final public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Swift.Void) { guard let localNotificationActionCapableSelf = self as? LocalNotificationActionCapable else { noteImproperAPIUsage("Received local notification action but \(self) does not conform to LocalNotificationActionCapable. Ignoring.") completionHandler() return } - localNotificationActionCapableSelf.handleLocalNotificationActionWithIdentifier(identifier, forLocalNotification: notification, withResponseInfo: nil, completionHandler: completionHandler) + localNotificationActionCapableSelf.handleLocalNotification(actionIdentifier: identifier, for: notification, withResponseInfo: nil, completionHandler: completionHandler) } - final public func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) { + @objc(application:handleActionWithIdentifier:forLocalNotification:withResponseInfo:completionHandler:) + final public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) { guard let localNotificationActionCapableSelf = self as? LocalNotificationActionCapable else { noteImproperAPIUsage("Received local notification action but \(self) does not conform to LocalNotificationActionCapable. Ignoring.") completionHandler() return } - localNotificationActionCapableSelf.handleLocalNotificationActionWithIdentifier(identifier, forLocalNotification: notification, withResponseInfo: responseInfo as? [String : AnyObject], completionHandler: completionHandler) + localNotificationActionCapableSelf.handleLocalNotification(actionIdentifier: identifier, for: notification, withResponseInfo: (responseInfo as! [String : Any]), completionHandler: completionHandler) } } diff --git a/Sources/SuperDelegate+OpenURL.swift b/Sources/SuperDelegate+OpenURL.swift index 7487aca..912051f 100644 --- a/Sources/SuperDelegate+OpenURL.swift +++ b/Sources/SuperDelegate+OpenURL.swift @@ -28,13 +28,11 @@ import Foundation public protocol OpenURLCapable: ApplicationLaunched { /// Called when your application has been launched due to a URL. /// @return Whether the URL can be handled from a cold start. - @warn_unused_result - func canOpenLaunchURL(launchURLToOpen: URLToOpen) -> Bool + func canOpen(launchURL: URLToOpen) -> Bool - /// Called when your application has been asked to open a URL. Will not be called for URLs that were delivered to the app via loadInterfaceWithLaunchItem(_:). + /// Called when your application has been asked to open a URL. Will not be called for URLs that were delivered to the app via loadInterface(launchItem:). /// @return Whether the URL was handled. - @warn_unused_result - func handleURLToOpen(urlToOpen: URLToOpen) -> Bool + func handle(urlToOpen: URLToOpen) -> Bool } @@ -43,15 +41,26 @@ public protocol OpenURLCapable: ApplicationLaunched { public struct URLToOpen: CustomStringConvertible, Equatable { /// The URL to open. - public let url: NSURL + public let url: URL /// The Bundle ID of the orgininating application. public let sourceApplicationBundleID: String? /// A property list object supplied by the source app to communicate information to the receiving app. - public let annotation: AnyObject? + public let annotation: Any? /// Set to true if the file needs to be copied before use. public let copyBeforeUse: Bool - public init(url: NSURL, sourceApplicationBundleID: String? = nil, annotation: AnyObject? = nil, copyBeforeUse: Bool = false) { + // MARK: Equatable + + public static func ==(lhs: URLToOpen, rhs: URLToOpen) -> Bool { + return lhs.url == rhs.url + && lhs.sourceApplicationBundleID == rhs.sourceApplicationBundleID + && lhs.copyBeforeUse == rhs.copyBeforeUse + // Unfortuantely we don't know .annotation's Type or whether it is Equatable so we can't use it here. + } + + // MARK: Initialization + + public init(url: URL, sourceApplicationBundleID: String? = nil, annotation: Any? = nil, copyBeforeUse: Bool = false) { self.url = url self.sourceApplicationBundleID = sourceApplicationBundleID self.annotation = annotation @@ -66,18 +75,6 @@ public struct URLToOpen: CustomStringConvertible, Equatable { } -// MARK: Equatable - - -@warn_unused_result -public func ==(lhs: URLToOpen, rhs: URLToOpen) -> Bool { - return lhs.url == rhs.url - && lhs.sourceApplicationBundleID == rhs.sourceApplicationBundleID - && lhs.copyBeforeUse == rhs.copyBeforeUse - // Unfortuantely we don't know .annotation's Type or whether it is Equatable so we can't use it here. -} - - // MARK: - SuperDelegate Open URL Extension @@ -87,9 +84,9 @@ extension SuperDelegate { // MARK: UIApplicationDelegate + @objc(application:openURL:options:) @available(iOS 9.0, *) - @warn_unused_result - final public func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { + final public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { guard let openURLCapableSelf = self as? OpenURLCapable else { noteImproperAPIUsage("Received openURL action but \(self) does not conform to OpenURLCapable. Ignoring.") return false @@ -100,16 +97,16 @@ extension SuperDelegate { return true } - let sourceApplicationBundleID = options[UIApplicationOpenURLOptionsSourceApplicationKey] as? String - let annotation = options[UIApplicationOpenURLOptionsAnnotationKey] - let copyBeforeUse = options[UIApplicationOpenURLOptionsOpenInPlaceKey] as? Bool ?? false + let sourceApplicationBundleID = options[.sourceApplication] as? String + let annotation = options[.annotation] + let copyBeforeUse = options[.openInPlace] as? Bool ?? false let urlToOpen = URLToOpen(url: url, sourceApplicationBundleID: sourceApplicationBundleID, annotation: annotation, copyBeforeUse: copyBeforeUse) - return openURLCapableSelf.handleURLToOpen(urlToOpen) + return openURLCapableSelf.handle(urlToOpen: urlToOpen) } - @warn_unused_result - final public func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { + @objc(application:openURL:sourceApplication:annotation:) + final public func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { guard let openURLCapableSelf = self as? OpenURLCapable else { noteImproperAPIUsage("Received openURL action but \(self) does not conform to OpenURLCapable. Ignoring.") return false @@ -122,13 +119,23 @@ extension SuperDelegate { let urlToOpen = URLToOpen(url: url, sourceApplicationBundleID: sourceApplication, annotation: annotation, copyBeforeUse: false) - return openURLCapableSelf.handleURLToOpen(urlToOpen) + return openURLCapableSelf.handle(urlToOpen: urlToOpen) } - @warn_unused_result - final public func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool { - // Nothing to do here. On iOS 8, application(_:openURL:sourceApplication:annotation:) will be called instead of this one. This method is declared to prevent subclasses from improperly adopting this API. + @objc(application:handleOpenURL:) + final public func application(_ application: UIApplication, handleOpen url: URL) -> Bool { + // Nothing to do here. On iOS 8, application(_:open:sourceApplication:annotation:) will be called instead of this one. This method is declared to prevent subclasses from improperly adopting this API. return false } +} + + +// MARK: – UIApplicationLaunchOptionsKey Extension + + +extension UIApplicationLaunchOptionsKey { + // UIApplicationLaunchOptionsKey.openInPlace can be passed into launchOptions, but the Swift 3 API doesn't acknowledge this. So we add it here manually. + @available(iOS 9.0, *) + public static let openInPlace = UIApplicationLaunchOptionsKey(rawValue: "UIApplicationOpenURLOptionsOpenInPlaceKey") } diff --git a/Sources/SuperDelegate+RemoteNotifications.swift b/Sources/SuperDelegate+RemoteNotifications.swift index 460548e..b6a11df 100644 --- a/Sources/SuperDelegate+RemoteNotifications.swift +++ b/Sources/SuperDelegate+RemoteNotifications.swift @@ -26,13 +26,13 @@ import Foundation public protocol RemoteNotificationCapable: ApplicationLaunched { /// Called whenever the app successfully registers for remote notifications. This method may be called many times during a single application launch. Use this method to hand your server your notification token. - func didRegisterForRemoteNotificationsWithToken(deviceToken: NSData) + func didRegisterForRemoteNotifications(withDeviceToken deviceToken: Data) /// Called when your app fails to register for remote notifications. There is no recovery mechanism once registration fails. In practice this method should almost never be called. Log the error or present it to the user. - func didFailToRegisterForRemoteNotificationsWithError(error: NSError) + func didFailToRegisterForRemoteNotifications(withError error: Error) - /// Called when your app receives a remote notification. Will not be called for notifications that were delivered to the app via loadInterfaceWithLaunchItem(_:). - func didReceiveRemoteNotification(remoteNotification: RemoteNotification, notificationOrigin: UserNotificationOrigin, fetchCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)) + /// Called when your app receives a remote notification. Will not be called for notifications that were delivered to the app via loadInterface(launchItem:). + func didReceive(remoteNotification: RemoteNotification, origin: UserNotificationOrigin, fetchCompletionHandler completionHandler: @escaping ((UIBackgroundFetchResult) -> Swift.Void)) } @@ -41,7 +41,7 @@ public protocol RemoteNotificationCapable: ApplicationLaunched { public protocol RemoteNotificationActionCapable: RemoteNotificationCapable, UserNotificationCapable { /// Called when your app has to handle a remote notification action tapped by the user. Execute completionHandler when your application has handled the action to prevent iOS from killing your app. - func handleRemoteNotificationActionWithIdentifier(actionIdentifier: String?, forRemoteNotification notification: RemoteNotification, withResponseInfo responseInfo: [String : AnyObject]?, completionHandler: () -> Void) + func handleRemoteNotificationAction(withActionIdentifier actionIdentifier: String?, forRemoteNotification notification: RemoteNotification, withResponseInfo responseInfo: [String : Any]?, completionHandler: @escaping () -> Swift.Void) } @@ -53,67 +53,66 @@ public extension SuperDelegate { // MARK: UIApplicationDelegate - - final public func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { + public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { guard let remoteNotificationsCapableSelf = self as? RemoteNotificationCapable else { noteImproperAPIUsage("SuperDelegate registered for remote notifications but \(self) does not conform to RemoteNotificationCapable. Ignoring.") return } - remoteNotificationsCapableSelf.didRegisterForRemoteNotificationsWithToken(deviceToken) + remoteNotificationsCapableSelf.didRegisterForRemoteNotifications(withDeviceToken: deviceToken) } - final public func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) { + final public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { guard let remoteNotificationsCapableSelf = self as? RemoteNotificationCapable else { noteImproperAPIUsage("SuperDelegate did fail to register for remote notifications but \(self) does not conform to RemoteNotificationCapable. Ignoring.") return } - remoteNotificationsCapableSelf.didFailToRegisterForRemoteNotificationsWithError(error) + remoteNotificationsCapableSelf.didFailToRegisterForRemoteNotifications(withError: error) } - final public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { + final public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) { guard let remoteNotificationsCapableSelf = self as? RemoteNotificationCapable else { noteImproperAPIUsage("Received remote notification but \(self) does not conform to RemoteNotificationCapable. Ignoring.") - completionHandler(.NoData) + completionHandler(.noData) return } guard let remoteNotification = RemoteNotification(remoteNotification: userInfo) else { // Bail out. We don't have a remote notification we understand. noteImproperAPIUsage("SuperDelegate could not parse remote notification \(userInfo)\nIgnoring") - completionHandler(.NoData) + completionHandler(.noData) return } guard launchOptionsRemoteNotification != remoteNotification else { // Bail out. We've already processed this notification. - completionHandler(.NoData) + completionHandler(.noData) return } let notificationOrigin: UserNotificationOrigin if applicationIsInForeground { - notificationOrigin = .DeliveredWhileInForground - } else if application.applicationState == .Background && remoteNotification.contentAvailable { - notificationOrigin = .DeliveredWhileInBackground + notificationOrigin = .deliveredWhileInForeground + } else if application.applicationState == .background && remoteNotification.contentAvailable { + notificationOrigin = .deliveredWhileInBackground } else { - notificationOrigin = .UserTappedToBringAppToForeground + notificationOrigin = .userTappedToBringAppToForeground } - remoteNotificationsCapableSelf.didReceiveRemoteNotification(remoteNotification, - notificationOrigin: notificationOrigin, - fetchCompletionHandler: completionHandler) + remoteNotificationsCapableSelf.didReceive(remoteNotification: remoteNotification, + origin: notificationOrigin, + fetchCompletionHandler: completionHandler) } - final public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { + final public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { // This method may be called if the application hasn't added "remote-notification" to the UIBackgroundModes array in Info.plist. - self.application(application, didReceiveRemoteNotification: userInfo) { (_) in + self.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: { (_) in // Nothing to do here. - } + }) } - final public func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], completionHandler: () -> Void) { + final public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) { guard let remoteNotificationActionCapableSelf = self as? RemoteNotificationActionCapable else { noteImproperAPIUsage("Received local notification action but \(self) does not conform to RemoteNotificationActionCapable. Ignoring.") completionHandler() @@ -127,10 +126,10 @@ public extension SuperDelegate { return } - remoteNotificationActionCapableSelf.handleRemoteNotificationActionWithIdentifier(identifier, forRemoteNotification: remoteNotification, withResponseInfo: nil, completionHandler: completionHandler) + remoteNotificationActionCapableSelf.handleRemoteNotificationAction(withActionIdentifier: identifier, forRemoteNotification: remoteNotification, withResponseInfo: nil, completionHandler: completionHandler) } - final public func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) { + final public func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Swift.Void) { guard let remoteNotificationActionCapableSelf = self as? RemoteNotificationActionCapable else { noteImproperAPIUsage("Received local notification action but \(self) does not conform to RemoteNotificationActionCapable. Ignoring.") completionHandler() @@ -144,7 +143,7 @@ public extension SuperDelegate { return } - remoteNotificationActionCapableSelf.handleRemoteNotificationActionWithIdentifier(identifier, forRemoteNotification: remoteNotification, withResponseInfo: responseInfo as? [String : AnyObject], completionHandler: completionHandler) + remoteNotificationActionCapableSelf.handleRemoteNotificationAction(withActionIdentifier: identifier, forRemoteNotification: remoteNotification, withResponseInfo: (responseInfo as! [String : Any]), completionHandler: completionHandler) } } diff --git a/Sources/SuperDelegate+Shortcuts.swift b/Sources/SuperDelegate+Shortcuts.swift index 1e34bed..aa7781f 100644 --- a/Sources/SuperDelegate+Shortcuts.swift +++ b/Sources/SuperDelegate+Shortcuts.swift @@ -27,11 +27,10 @@ import Foundation @available(iOS 9.0, *) public protocol ShortcutCapable: ApplicationLaunched { /// Called whenever iOS informs SuperDelgate of a UIApplicationShortItem to process. Guaranteed to be called after setupApplication(). - @warn_unused_result - func canHandleShortcutItem(shortcutItem: UIApplicationShortcutItem) -> Bool + func canHandle(shortcutItem: UIApplicationShortcutItem) -> Bool - /// Called when your app receives a shortcut item. Will not be called for shortcuts that were delivered to the app via loadInterfaceWithLaunchItem(_:). Guaranteed not to be called with a shortcut item your app can not handle. Execute completionHandler when your application has handled the shortcut. - func handleShortcutItem(shortcutItem: UIApplicationShortcutItem, completionHandler: () -> Void) + /// Called when your app receives a shortcut item. Will not be called for shortcuts that were delivered to the app via loadInterface(launchItem:). Guaranteed not to be called with a shortcut item your app can not handle. Execute completionHandler when your application has handled the shortcut. + func handle(shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping () -> Swift.Void) } @@ -44,18 +43,19 @@ extension SuperDelegate { // MARK: UIApplicationDelegate + @objc(application:performActionForShortcutItem:completionHandler:) @available(iOS 9.0, *) - final public func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) { + final public func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Swift.Void) { guard let shortcutCapableSelf = self as? ShortcutCapable else { noteImproperAPIUsage("Received shortcut item but \(self) does not conform to ShortcutCapable. Ignoring.") completionHandler(false) return } - let canHandleShortcutItem = shortcutCapableSelf.canHandleShortcutItem(shortcutItem) + let canHandleShortcutItem = shortcutCapableSelf.canHandle(shortcutItem: shortcutItem) if canHandleShortcutItem { - shortcutCapableSelf.handleShortcutItem(shortcutItem) { + shortcutCapableSelf.handle(shortcutItem: shortcutItem) { // Since we know the app can handle the shortcut item, we can assume handling it was successful. completionHandler(true) } diff --git a/Sources/SuperDelegate+StateRestoration.swift b/Sources/SuperDelegate+StateRestoration.swift index 8c76b8b..71ce657 100644 --- a/Sources/SuperDelegate+StateRestoration.swift +++ b/Sources/SuperDelegate+StateRestoration.swift @@ -26,22 +26,19 @@ import Foundation public protocol StateRestorationCapable: ApplicationLaunched { /// Called when your app can save its application state for restoration. Returns whether the app should save the current state. - @warn_unused_result - func shouldSaveApplicationState(coder: NSCoder) -> Bool + func shouldSaveApplicationState(using coder: NSCoder) -> Bool /// Called when your app can restore its application state after its interface has been loaded. Returns whether the app should restore. - @warn_unused_result - func shouldRestoreApplicationState(coder: NSCoder) -> Bool + func shouldRestoreApplicationState(using coder: NSCoder) -> Bool /// Tells your delegate to save any high-level state information at the beginning of the state preservation process. - func willEncodeRestorableStateWithCoder(coder: NSCoder) + func willEncodeRestorableState(using coder: NSCoder) /// Tells your delegate to restore any high-level state information as part of the state restoration process. - func didDecodeRestorableStateWithCoder(coder: NSCoder) + func didDecodeRestorableState(using coder: NSCoder) /// Asks your app to provide the specified view controller during state restoration. - @warn_unused_result - func viewControllerWithRestorationIdentifierPath(identifierComponents: [AnyObject], coder: NSCoder) -> UIViewController? + func viewControllerWithRestorationIdentifierPath(identifierComponents: [Any], coder: NSCoder) -> UIViewController? } @@ -54,52 +51,51 @@ extension SuperDelegate { // MARK: UIApplicationDelegate - @warn_unused_result - final public func application(application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool { + final public func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool { guard let stateRestorationCapableSelf = self as? StateRestorationCapable else { // Nothing to do here. return false } - return stateRestorationCapableSelf.shouldSaveApplicationState(coder) + return stateRestorationCapableSelf.shouldSaveApplicationState(using: coder) } - @warn_unused_result - final public func application(application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool { + final public func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool { guard let stateRestorationCapableSelf = self as? StateRestorationCapable else { // Nothing to do here. return false } - return stateRestorationCapableSelf.shouldRestoreApplicationState(coder) + return stateRestorationCapableSelf.shouldRestoreApplicationState(using: coder) } - final public func application(application: UIApplication, willEncodeRestorableStateWithCoder coder: NSCoder) { + @objc(application:willEncodeRestorableStateWithCoder:) + final public func application(_ application: UIApplication, willEncodeRestorableStateWith coder: NSCoder) { guard let stateRestorationCapableSelf = self as? StateRestorationCapable else { // Nothing to do here. return } - stateRestorationCapableSelf.willEncodeRestorableStateWithCoder(coder) + stateRestorationCapableSelf.willEncodeRestorableState(using: coder) } - final public func application(application: UIApplication, didDecodeRestorableStateWithCoder coder: NSCoder) { + @objc(application:didDecodeRestorableStateWithCoder:) + final public func application(_ application: UIApplication, didDecodeRestorableStateWith coder: NSCoder) { guard let stateRestorationCapableSelf = self as? StateRestorationCapable else { // Nothing to do here. return } - stateRestorationCapableSelf.didDecodeRestorableStateWithCoder(coder) + stateRestorationCapableSelf.didDecodeRestorableState(using: coder) } - @warn_unused_result - final public func application(application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [AnyObject], coder: NSCoder) -> UIViewController? { + final public func application(_ application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [Any], coder: NSCoder) -> UIViewController? { guard let stateRestorationCapableSelf = self as? StateRestorationCapable else { noteImproperAPIUsage("Received viewControllerWithRestorationIdentifierPath but \(self) does not conform to StateRestorationCapable. Not handling state restoration event.") return nil } - return stateRestorationCapableSelf.viewControllerWithRestorationIdentifierPath(identifierComponents, coder: coder) + return stateRestorationCapableSelf.viewControllerWithRestorationIdentifierPath(identifierComponents: identifierComponents, coder: coder) } } diff --git a/Sources/SuperDelegate+UserActivity.swift b/Sources/SuperDelegate+UserActivity.swift index 83da396..3aa0698 100644 --- a/Sources/SuperDelegate+UserActivity.swift +++ b/Sources/SuperDelegate+UserActivity.swift @@ -27,13 +27,11 @@ import Foundation public protocol UserActivityCapable: ApplicationLaunched { /// Called whenever your application must handle a user activity. /// @return Whether you can handle the user activity. Returning false means the below methods will not be called. - @warn_unused_result - func canHandleUserActivity(userActivity: NSUserActivity) -> Bool + func canResume(userActivity: NSUserActivity) -> Bool /// Called whenever your application must continue a user activity after the interface has been loaded. /// @return true if your app handled the user activity, false if it did not. - @warn_unused_result - func continueUserActivity(userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool + func resume(userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Swift.Void) -> Bool } @@ -46,8 +44,8 @@ extension SuperDelegate { // MARK: UIApplicationDelegate - @warn_unused_result - final public func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool { + @objc(application:continueUserActivity:restorationHandler:) + final public func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Swift.Void) -> Bool { guard let userActivityCapableSelf = self as? UserActivityCapable else { noteImproperAPIUsage("Received continueUserActivity but \(self) does not conform to UserActivityCapable. Not handling user activity event.") return false @@ -58,17 +56,21 @@ extension SuperDelegate { return true } - guard userActivityCapableSelf.canHandleUserActivity(userActivity) else { + guard userActivityCapableSelf.canResume(userActivity: userActivity) else { return false } - return userActivityCapableSelf.continueUserActivity(userActivity, restorationHandler: restorationHandler) + return userActivityCapableSelf.resume(userActivity: userActivity, restorationHandler: restorationHandler) } } -// MARK: Undocumented Launch Options Keys +// MARK: – UIApplicationLaunchOptionsKey Extension -let ApplicationLaunchOptionsUserActivityKey = "UIApplicationLaunchOptionsUserActivityKey" +extension UIApplicationLaunchOptionsKey { + + // UIApplicationLaunchOptionsKey.userActivity is passed into launchOptions, but the API doesn't acknowledge this. So we add it here manually. + public static let userActivity = UIApplicationLaunchOptionsKey(rawValue: "UIApplicationLaunchOptionsUserActivityKey") +} diff --git a/Sources/SuperDelegate+UserNotifications.swift b/Sources/SuperDelegate+UserNotifications.swift index 55c842c..a5db591 100644 --- a/Sources/SuperDelegate+UserNotifications.swift +++ b/Sources/SuperDelegate+UserNotifications.swift @@ -26,11 +26,10 @@ import Foundation public protocol UserNotificationCapable: ApplicationLaunched { /// Called when your app registers for user notifications. - @warn_unused_result func requestedUserNotificationSettings() -> UIUserNotificationSettings /// Called every time user notifications are registered. Will happen every time the application is brought to the foreground after requestUserNotificationPermissions is called. - func didReceiveUserNotificationPermissions(userNotificationPermissionsGranted: UserNotificationPermissionsGranted) + func didReceive(userNotificationPermissions: UserNotificationPermissionsGranted) } @@ -39,49 +38,48 @@ public protocol UserNotificationCapable: ApplicationLaunched { public enum UserNotificationPermissionsGranted: Equatable { /// None of the permissions detailed in requestedUserNotificationSettings().types are granted. - case None - /// Some of the permissions detailed in requestedUserNotificationSettings().types are granted. - case Some(grantedPermissions: UIUserNotificationType) + case none + /// A partial set of the permissions detailed in requestedUserNotificationSettings().types are granted. + case partial(grantedPermissions: UIUserNotificationType) /// All of the permissions detailed in requestedUserNotificationSettings().types are granted. - case Requested + case requested + + // MARK: Equatable + + public static func ==(lhs: UserNotificationPermissionsGranted, rhs: UserNotificationPermissionsGranted) -> Bool { + switch (lhs, rhs) { + case (.requested, .requested): + return true + case let (.partial(lhsGrantedPermissions), .partial(rhsGrantedPermissions)) where lhsGrantedPermissions == rhsGrantedPermissions: + return true + case (.none, .none): + return true + default: + return false + } + } + + // MARK: Initialization internal init(grantedPermissions: UIUserNotificationType, preferredPermissions: UIUserNotificationType) { if grantedPermissions.rawValue & preferredPermissions.rawValue == preferredPermissions.rawValue { - self = .Requested - } else if grantedPermissions.rawValue & preferredPermissions.rawValue != UIUserNotificationType.None.rawValue { - self = .Some(grantedPermissions: grantedPermissions) + self = .requested + } else if grantedPermissions != [] { + self = .partial(grantedPermissions: grantedPermissions) } else { - self = .None + self = .none } } } -// MARK: Equatable - - -@warn_unused_result -public func ==(lhs: UserNotificationPermissionsGranted, rhs: UserNotificationPermissionsGranted) -> Bool { - switch (lhs, rhs) { - case (.Requested, .Requested): - return true - case let (.Some(lhsGrantedPermissions), .Some(rhsGrantedPermissions)) where lhsGrantedPermissions == rhsGrantedPermissions: - return true - case (.None, .None): - return true - default: - return false - } -} - - public enum UserNotificationOrigin { /// The user tapped the notification to bring the app to the foreground - case UserTappedToBringAppToForeground + case userTappedToBringAppToForeground /// The user has not seen the notification since it was delivered while the app was in the foreground - case DeliveredWhileInForground + case deliveredWhileInForeground /// The user may have seen the notification, but hasn't tapped on it. RemoteNotification - case DeliveredWhileInBackground + case deliveredWhileInBackground } @@ -94,7 +92,7 @@ extension SuperDelegate { // MARK: Public Methods - /// Requests the user notification permissions defined by requestedUserNotificationSettings(). Call this when the user should be prompted for user notification permissions. The first time (per installation and requestedUserNotificationSettings().types configuration) that this method is called the user will be prompted for user notification permissions. Subsequent attempts will not prompt users, but will result in didReceiveUserNotificationPermissions(_:) being called. + /// Requests the user notification permissions defined by requestedUserNotificationSettings(). Call this when the user should be prompted for user notification permissions. The first time (per installation and requestedUserNotificationSettings().types configuration) that this method is called the user will be prompted for user notification permissions. Subsequent attempts will not prompt users, but will result in didReceive(userNotificationPermissions:) being called. final public func requestUserNotificationPermissions() { guard let userNotificationsCapableSelf = self as? UserNotificationCapable else { noteImproperAPIUsage("Attempting to requestUserNotificationPermissions when app \(self) subclass does not conform to UserNotificationCapable protocol.") @@ -104,7 +102,7 @@ extension SuperDelegate { // Note that we have registered for user notifications. Every time the the app comes to the foreground in the future (with the same requestedUserNotificationSettings()) we'll register on the application's behalf. Registering on every applicationDidEnterForeground allows the app to always know the device's current notification settings. previouslyRequestedUserNotificationPermissions = true - UIApplication.sharedApplication().registerUserNotificationSettings(userNotificationsCapableSelf.requestedUserNotificationSettings()) + UIApplication.shared.registerUserNotificationSettings(userNotificationsCapableSelf.requestedUserNotificationSettings()) } @@ -121,7 +119,7 @@ extension SuperDelegate { return false } - return NSUserDefaults.standardUserDefaults().boolForKey("\(SuperDelegate.PreviouslyRequestedUserNotificationPermissionsPreferencesKey).\(userNotificationsCapableSelf.requestedUserNotificationSettings().types)") + return UserDefaults.standard.bool(forKey: "\(SuperDelegate.PreviouslyRequestedUserNotificationPermissionsPreferencesKey).\(userNotificationsCapableSelf.requestedUserNotificationSettings().types)") } set { @@ -130,7 +128,7 @@ extension SuperDelegate { return } - NSUserDefaults.standardUserDefaults().setBool(newValue, forKey: "\(SuperDelegate.PreviouslyRequestedUserNotificationPermissionsPreferencesKey).\(userNotificationsCapableSelf.requestedUserNotificationSettings().types)") + UserDefaults.standard.set(newValue, forKey: "\(SuperDelegate.PreviouslyRequestedUserNotificationPermissionsPreferencesKey).\(userNotificationsCapableSelf.requestedUserNotificationSettings().types)") } } @@ -138,19 +136,20 @@ extension SuperDelegate { // MARK: UIApplicationDelegate - final public func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) { + @objc(application:didRegisterUserNotificationSettings:) + final public func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { guard let userNotificationsCapableSelf = self as? UserNotificationCapable else { noteImproperAPIUsage("Received didRegisterUserNotificationSettings but \(self) does not conform to UserNotificationCapable.") return } - if let currentUserNotificationSettings = application.currentUserNotificationSettings() { + if let currentUserNotificationSettings = application.currentUserNotificationSettings { // Some versions of iOS give us an incomplete notificationSettings options. Therefore, union the options with currentUserNotificationSettings to work around possible bugs in the operating system. let grantedPermissions = currentUserNotificationSettings.types.union(notificationSettings.types) - userNotificationsCapableSelf.didReceiveUserNotificationPermissions(UserNotificationPermissionsGranted(grantedPermissions: grantedPermissions, preferredPermissions: userNotificationsCapableSelf.requestedUserNotificationSettings().types)) + userNotificationsCapableSelf.didReceive(userNotificationPermissions: UserNotificationPermissionsGranted(grantedPermissions: grantedPermissions, preferredPermissions: userNotificationsCapableSelf.requestedUserNotificationSettings().types)) } else { - userNotificationsCapableSelf.didReceiveUserNotificationPermissions(UserNotificationPermissionsGranted(grantedPermissions: notificationSettings.types, preferredPermissions: userNotificationsCapableSelf.requestedUserNotificationSettings().types)) + userNotificationsCapableSelf.didReceive(userNotificationPermissions: UserNotificationPermissionsGranted(grantedPermissions: notificationSettings.types, preferredPermissions: userNotificationsCapableSelf.requestedUserNotificationSettings().types)) } } } diff --git a/Sources/SuperDelegate+WatchKit.swift b/Sources/SuperDelegate+WatchKit.swift index 0f35639..391a465 100644 --- a/Sources/SuperDelegate+WatchKit.swift +++ b/Sources/SuperDelegate+WatchKit.swift @@ -26,7 +26,7 @@ import Foundation public protocol WatchKitCapable: ApplicationLaunched { /// Called when your app receives a request from the WatchKit extension - func handleWatchKitExtensionRequest(userInfo: [NSObject : AnyObject]?, reply: ([NSObject : AnyObject]?) -> Void) + func handleWatchKitExtensionRequest(userInfo: [AnyHashable : Any]?, reply: @escaping ([AnyHashable : Any]?) -> Swift.Void) } @@ -39,7 +39,7 @@ extension SuperDelegate { // MARK: UIApplicationDelegate - final public func application(application: UIApplication, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]?, reply: ([NSObject : AnyObject]?) -> Void) { + final public func application(_ application: UIApplication, handleWatchKitExtensionRequest userInfo: [AnyHashable : Any]?, reply: @escaping ([AnyHashable : Any]?) -> Swift.Void) { guard let watchKitCapableSelf = self as? WatchKitCapable else { noteImproperAPIUsage("Received WatchKit extension request but \(self) does not conform to WatchKitCapable. Ignoring.") reply(nil) @@ -49,6 +49,6 @@ extension SuperDelegate { // iOS 8.4 calls application(_:handleWatchKitExtensionRequest:userInfo:reply:) prior to the application finishing launching. Make sure our application is set up once. setupApplicationOnce() - watchKitCapableSelf.handleWatchKitExtensionRequest(userInfo, reply: reply) + watchKitCapableSelf.handleWatchKitExtensionRequest(userInfo: userInfo, reply: reply) } } diff --git a/Sources/SuperDelegate.swift b/Sources/SuperDelegate.swift index 28df87e..774917a 100644 --- a/Sources/SuperDelegate.swift +++ b/Sources/SuperDelegate.swift @@ -28,14 +28,14 @@ public protocol ApplicationLaunched { /// Very first method that SuperDelegate calls on launch. Guaranteed to only be called once. func setupApplication() /// Called when the app launches. Guaranteed to only be called once. - func loadInterfaceWithLaunchItem(launchItem: LaunchItem) + func loadInterface(launchItem: LaunchItem) } // MARK: - SuperDelegate -public class SuperDelegate: NSObject, UIApplicationDelegate { +open class SuperDelegate: NSObject, UIApplicationDelegate { // MARK: Public Properties @@ -48,15 +48,15 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { private var withinLoadInterface = false - /// Convenience method to set up the main window. Must be called from loadInterfaceWithLaunchItem(_:). - public func setupMainWindow(window: UIWindow) { + /// Convenience method to set up the main window. Must be called from loadInterface(launchItem:). + public func setup(mainWindow: UIWindow) { guard withinLoadInterface else { - noteImproperAPIUsage("Must call \(#function) from within loadInterfaceWithLaunchItem(_:)") + noteImproperAPIUsage("Must call \(#function) from within loadInterface(launchItem:)") return } - window.frame = UIScreen.mainScreen().bounds - window.makeKeyAndVisible() + mainWindow.frame = UIScreen.main.bounds + mainWindow.makeKeyAndVisible() } @@ -66,8 +66,8 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { private var handledShortcutInWillFinishLaunching = false private var couldHandleURLInWillFinishLaunching = true private var couldHandleUserActivityInWillFinishLaunching = true - @warn_unused_result - final public func application(application: UIApplication, willFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool { + + final public func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { guard self is ApplicationLaunched else { noteImproperAPIUsage("\(self) must conform to ApplicationLaunched protocol") return false @@ -77,55 +77,55 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { requestUserNotificationPermissionsIfPreviouslyRegistered() // Use notification listeners to respond to application lifecycle events to subclasses can override the default hooks. - applicationDidBecomeActiveListener = NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidBecomeActiveNotification, object: application, queue: NSOperationQueue.mainQueue()) { [weak self] _ in + applicationDidBecomeActiveListener = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationDidBecomeActive, object: application, queue: OperationQueue.main) { [weak self] _ in self?.applicationIsInForeground = true } - applicationDidEnterBackgroundListener = NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidEnterBackgroundNotification, object: application, queue: NSOperationQueue.mainQueue()) { [weak self] _ in + applicationDidEnterBackgroundListener = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationDidEnterBackground, object: application, queue: OperationQueue.main) { [weak self] _ in self?.applicationIsInForeground = false } var launchItem = LaunchItem(launchOptions: launchOptions) switch launchItem { - case let .ShortcutItem(launchShortcutItem): + case let .shortcut(launchShortcutItem): if #available(iOS 9.0, *) { guard let shortcutCapableSelf = self as? ShortcutCapable else { noteImproperAPIUsage("Received shortcut item but \(self) does not conform to ShortcutCapable. Not handling shortcut.") return true } - handledShortcutInWillFinishLaunching = shortcutCapableSelf.canHandleShortcutItem(launchShortcutItem) + handledShortcutInWillFinishLaunching = shortcutCapableSelf.canHandle(shortcutItem: launchShortcutItem) if !handledShortcutInWillFinishLaunching { - launchItem = .NoItem + launchItem = .none } } else { // Should not be possible. noteImproperAPIUsage("Launched due to ShortcutItem but not running iOS 9 or later.") - launchItem = .NoItem + launchItem = .none } - case let .UserActivityItem(launchUserActivity): + case let .userActivity(launchUserActivity): guard let userActivityCapableSelf = self as? UserActivityCapable else { noteImproperAPIUsage("Received user activity item but \(self) does not conform to UserActivityCapable. Not handling user activity.") return false } - couldHandleUserActivityInWillFinishLaunching = userActivityCapableSelf.canHandleUserActivity(launchUserActivity) + couldHandleUserActivityInWillFinishLaunching = userActivityCapableSelf.canResume(userActivity: launchUserActivity) if !couldHandleUserActivityInWillFinishLaunching { - launchItem = .NoItem + launchItem = .none } - case let .OpenURLItem(launchURLToOpen): + case let .openURL(launchURLToOpen): guard let openURLCapableSelf = self as? OpenURLCapable else { noteImproperAPIUsage("Received openURL action but \(self) does not conform to OpenURLCapable. Not handling URL.") return false } - couldHandleURLInWillFinishLaunching = openURLCapableSelf.canOpenLaunchURL(launchURLToOpen) + couldHandleURLInWillFinishLaunching = openURLCapableSelf.canOpen(launchURL: launchURLToOpen) if !couldHandleURLInWillFinishLaunching { - launchItem = .NoItem + launchItem = .none } - case .RemoteNotificationItem, .LocalNotificationItem, .NoItem: + case .remoteNotification, .localNotification, .none: // Nothing to do. break } @@ -134,7 +134,7 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { if self is StateRestorationCapable { // Per Apple's docs: If your app relies on the state restoration machinery to restore its view controllers, always show your app’s window from this method. Do not show the window in your app’s application:didFinishLaunchingWithOptions: method. Calling the window’s makeKeyAndVisible method does not make the window visible right away anyway. UIKit waits until your app’s application:didFinishLaunchingWithOptions: method finishes before making the window visible on the screen. - loadInterfaceOnceWithLaunchItem(launchItem) + loadInterfaceOnce(with: launchItem) } return true @@ -146,8 +146,7 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { && !handledShortcutInWillFinishLaunching } - @warn_unused_result - final public func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool { + final public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { guard self is ApplicationLaunched else { noteImproperAPIUsage("\(self) must conform to ApplicationLaunched protocol") return false @@ -157,25 +156,25 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { application.registerForRemoteNotifications() } - if let launchBluetoothPeripheralIdentifiers = launchOptions?[UIApplicationLaunchOptionsBluetoothPeripheralsKey] as? [String] { + if let launchBluetoothPeripheralIdentifiers = launchOptions?[UIApplicationLaunchOptionsKey.bluetoothPeripherals] as? [String] { guard let backgroundBluetoothPeripheralCapableSelf = self as? BackgroundBluetoothPeripheralCapable else { noteImproperAPIUsage("Received background bluetooth peripheral restore identifier but \(self) does not conform to BackgroundBluetoothPeripheralCapable. Failing to launch app.") return false } - backgroundBluetoothPeripheralCapableSelf.restoreBluetoothPeripheralManagersWithIdentifiers(launchBluetoothPeripheralIdentifiers) + backgroundBluetoothPeripheralCapableSelf.restoreBluetoothPeripheralManagers(withIdentifiers: launchBluetoothPeripheralIdentifiers) } - if let launchBluetoothCentralIdentifiers = launchOptions?[UIApplicationLaunchOptionsBluetoothCentralsKey] as? [String] { + if let launchBluetoothCentralIdentifiers = launchOptions?[UIApplicationLaunchOptionsKey.bluetoothCentrals] as? [String] { guard let backgroundBluetoothCentralCapableSelf = self as? BackgroundBluetoothCentralCapable else { noteImproperAPIUsage("Received background bluetooth peripheral restore identifier but \(self) does not conform to BackgroundBluetoothCentralCapable. Failing to launch app.") return false } - backgroundBluetoothCentralCapableSelf.restoreBluetoothCentralManagersWithIdentifiers(launchBluetoothCentralIdentifiers) + backgroundBluetoothCentralCapableSelf.restoreBluetoothCentralManagers(withIdentifiers: launchBluetoothCentralIdentifiers) } - if let launchDueToLocationEvent = launchOptions?[UIApplicationLaunchOptionsLocationKey] as? Bool where launchDueToLocationEvent { + if let launchDueToLocationEvent = launchOptions?[UIApplicationLaunchOptionsKey.location] as? Bool, launchDueToLocationEvent { guard let locationEventCapableSelf = self as? LocationEventCapable else { noteImproperAPIUsage("Launched due to location event but \(self) does not conform to LocationEventCapable. Failing to launch app.") return false @@ -186,47 +185,47 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { var launchItem = LaunchItem(launchOptions: launchOptions) switch launchItem { - case .ShortcutItem: + case .shortcut: if !handledShortcutInWillFinishLaunching { - launchItem = .NoItem + launchItem = .none } - case let .UserActivityItem(userActivity): + case let .userActivity(item): if couldHandleUserActivityInWillFinishLaunching { - launchOptionsUserActivity = userActivity + launchOptionsUserActivity = item } else { - launchItem = .NoItem + launchItem = .none } - case let .OpenURLItem(urlToOpen): + case let .openURL(item): if couldHandleURLInWillFinishLaunching { - launchOptionsURLToOpen = urlToOpen.url + launchOptionsURLToOpen = item.url } else { - launchItem = .NoItem + launchItem = .none } - case let .RemoteNotificationItem(remoteNotification): - launchOptionsRemoteNotification = remoteNotification + case let .remoteNotification(item): + launchOptionsRemoteNotification = item - case let .LocalNotificationItem(localNotification): - launchOptionsLocalNotification = localNotification + case let .localNotification(item): + launchOptionsLocalNotification = item - case .NoItem: + case .none: // Nothing to do. break } - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64(5.0) * Int64(NSEC_PER_SEC))), dispatch_get_main_queue(), { + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(5), execute: { self.launchOptionsUserActivity = nil self.launchOptionsURLToOpen = nil self.launchOptionsRemoteNotification = nil self.launchOptionsLocalNotification = nil }) - loadInterfaceOnceWithLaunchItem(launchItem) + loadInterfaceOnce(with: launchItem) // Now that we've loaded the interface with our launch item, set up our willEnterForegroundListener - applicationWillEnterForegroundListener = NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationWillEnterForegroundNotification, object: application, queue: NSOperationQueue.mainQueue()) { [weak self] _ in + applicationWillEnterForegroundListener = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationWillEnterForeground, object: application, queue: OperationQueue.main) { [weak self] _ in guard let weakSelf = self else { return } @@ -256,21 +255,21 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { /// iOS 8 and 9 deliver the same remote notification via launchOptions and then via application(_:didReceiveRemoteNotification:fetchCompletionHandler:). Protect against processing twice by storing the launchOptionsRemoteNotification, and not processing notifications that are equal to it immediately after launch. var launchOptionsRemoteNotification: RemoteNotification? - - /// iOS 8 and 9 deliver the same local notification via launchOptions and then via application(_:didReceiveLocalNotification:). Protect against processing twice by storing the launchOptionsLocalNotification, and not processing notifications that are equal to it immediately after launch. + + /// iOS 8 and 9 deliver the same local notification via launchOptions and then via application(_:didReceive:). Protect against processing twice by storing the launchOptionsLocalNotification, and not processing notifications that are equal to it immediately after launch. var launchOptionsLocalNotification: UILocalNotification? - /// iOS 8 and 9 deliver the same URL via launchOptions and then via application(_:openURL:*:). Protect against processing twice by storing the launchOptionsURLToOpen, and not processing URLs that are equal to it immediately after launch. - var launchOptionsURLToOpen: NSURL? + /// iOS 8 and 9 deliver the same URL via launchOptions and then via application(_:open:*:). Protect against processing twice by storing the launchOptionsURLToOpen, and not processing URLs that are equal to it immediately after launch. + var launchOptionsURLToOpen: URL? - /// iOS 8 and 9 deliver the same URL via launchOptions and then via application(_:continueUserActivity:restorationHandler:). Protect against processing twice by storing the launchOptionsUserActivity, and not processing user activity items that are equal to it immediately after launch. + /// iOS 8 and 9 deliver the same URL via launchOptions and then via application(_:continue:restorationHandler:). Protect against processing twice by storing the launchOptionsUserActivity, and not processing user activity items that are equal to it immediately after launch. var launchOptionsUserActivity: NSUserActivity? // MARK: Internal Methods - func noteImproperAPIUsage(text: String) { + func noteImproperAPIUsage(_ text: String) { assertionFailure("Improper SuperDelegate API Usage: \(text)") } @@ -292,7 +291,7 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { } var interfaceLoaded = false - func loadInterfaceOnceWithLaunchItem(launchItem: LaunchItem) { + func loadInterfaceOnce(with launchItem: LaunchItem) { // iOS 8.0 introduced a bug (fixed in 8.3) where loading UI on a 32bit device while the app is in the .Background state can cause a crash due to CUIShapeEffectStack.sharedCIContext() trying to access the GPU when created outside of application(_:applicationDidFinishLaunching:options:). Hack around the problem by creating a sharedCIContext within application(_:application*FinishLaunching:options:) by creating a dummy navigation bar and laying it out. For more details, see https://devforums.apple.com/thread/246744 UINavigationBar(frame: CGRect(x: 0, y: 0, width: 1, height: 1)).layoutSubviews() @@ -306,7 +305,7 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { return } withinLoadInterface = true - applicationLaunchedSelf.loadInterfaceWithLaunchItem(launchItem) + applicationLaunchedSelf.loadInterface(launchItem: launchItem) withinLoadInterface = false interfaceLoaded = true @@ -316,9 +315,9 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { // MARK: Private Properties - private var applicationDidBecomeActiveListener: AnyObject? - private var applicationWillEnterForegroundListener: AnyObject? - private var applicationDidEnterBackgroundListener: AnyObject? + private var applicationDidBecomeActiveListener: NSObjectProtocol? + private var applicationWillEnterForegroundListener: NSObjectProtocol? + private var applicationDidEnterBackgroundListener: NSObjectProtocol? // MARK: Private Methods @@ -340,13 +339,13 @@ public class SuperDelegate: NSObject, UIApplicationDelegate { } if let applicationDidBecomeActiveListener = applicationDidBecomeActiveListener { - NSNotificationCenter.defaultCenter().removeObserver(applicationDidBecomeActiveListener) + NotificationCenter.default.removeObserver(applicationDidBecomeActiveListener) } if let applicationWillEnterForegroundListener = applicationWillEnterForegroundListener { - NSNotificationCenter.defaultCenter().removeObserver(applicationWillEnterForegroundListener) + NotificationCenter.default.removeObserver(applicationWillEnterForegroundListener) } if let applicationDidEnterBackgroundListener = applicationDidEnterBackgroundListener { - NSNotificationCenter.defaultCenter().removeObserver(applicationDidEnterBackgroundListener) + NotificationCenter.default.removeObserver(applicationDidEnterBackgroundListener) } } } diff --git a/SuperDelegate.podspec b/SuperDelegate.podspec index 5add281..bc0152a 100644 --- a/SuperDelegate.podspec +++ b/SuperDelegate.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'SuperDelegate' - s.version = '0.8.2' + s.version = '0.9.0' s.license = 'Apache License, Version 2.0' s.summary = 'SuperDelegate provides a clean application delegate interface and protects you from bugs in the application lifecycle.' s.homepage = 'https://github.com/square/SuperDelegate' diff --git a/SuperDelegate.xcodeproj/project.pbxproj b/SuperDelegate.xcodeproj/project.pbxproj index 6146df7..1e7ffa9 100644 --- a/SuperDelegate.xcodeproj/project.pbxproj +++ b/SuperDelegate.xcodeproj/project.pbxproj @@ -220,14 +220,18 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Square, Inc."; TargetAttributes = { EA65F98D1CBF06EB00CBA8E3 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; }; EA65F9971CBF06EB00CBA8E3 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; + ProvisioningStyle = Automatic; }; }; }; @@ -361,7 +365,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -403,7 +407,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -415,6 +419,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -426,6 +431,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -433,6 +439,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -443,26 +450,33 @@ PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SuperDelegate; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; EA65F9A61CBF06EB00CBA8E3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SuperDelegateTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; EA65F9A71CBF06EB00CBA8E3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.SuperDelegateTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/SuperDelegate.xcodeproj/xcshareddata/xcschemes/SuperDelegate.xcscheme b/SuperDelegate.xcodeproj/xcshareddata/xcschemes/SuperDelegate.xcscheme index 0aa3040..badfccb 100644 --- a/SuperDelegate.xcodeproj/xcshareddata/xcschemes/SuperDelegate.xcscheme +++ b/SuperDelegate.xcodeproj/xcshareddata/xcschemes/SuperDelegate.xcscheme @@ -1,6 +1,6 @@ Void) { + var handledResponseInfo: [String : Any]? = nil + func handleLocalNotification(actionIdentifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [String : Any]?, completionHandler: @escaping () -> Swift.Void) { handledActionIdentifier = actionIdentifier handledLocalNotification = notification handledResponseInfo = responseInfo diff --git a/Tests/SuperDelegate+LocationEventsTests.swift b/Tests/SuperDelegate+LocationEventsTests.swift index 70f92f6..a08cbff 100644 --- a/Tests/SuperDelegate+LocationEventsTests.swift +++ b/Tests/SuperDelegate+LocationEventsTests.swift @@ -30,14 +30,14 @@ class SuperDelegateLocationEventsTests: SuperDelegateTests { func test_applicationDidFinishLaunching_notifiesAboutLocationEvent() { let locationEventsCapableDelegate = LocationEventsCapableDelegate() - XCTAssertTrue(locationEventsCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: [UIApplicationLaunchOptionsLocationKey : true])) + XCTAssertTrue(locationEventsCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: [UIApplicationLaunchOptionsKey.location : true])) XCTAssertTrue(locationEventsCapableDelegate.appLaunchedDuetoLocationEvent) } func test_applicationWillFinishLaunching_doesNotNotifyAboutLocationEvent() { let locationEventsCapableDelegate = LocationEventsCapableDelegate() - XCTAssertTrue(locationEventsCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsLocationKey : true])) + XCTAssertTrue(locationEventsCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsKey.location : true])) XCTAssertFalse(locationEventsCapableDelegate.appLaunchedDuetoLocationEvent) } } diff --git a/Tests/SuperDelegate+OpenURLTests.swift b/Tests/SuperDelegate+OpenURLTests.swift index f36f6ec..b4da421 100644 --- a/Tests/SuperDelegate+OpenURLTests.swift +++ b/Tests/SuperDelegate+OpenURLTests.swift @@ -30,75 +30,75 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { func test_applicationDidFinishLaunching_doesNotLoadInterfaceWithURLIfCanOpenLaunchURLFails() { let openURLCapableDelegate = OpenURLCapableDelegate() - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 let copyBeforeUse = true openURLCapableDelegate.shouldOpenNextURL = false - let launchOptions: [String : AnyObject] + let launchOptions: [UIApplicationLaunchOptionsKey : Any] if #available(iOS 9.0, *) { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation, - UIApplicationOpenURLOptionsOpenInPlaceKey : copyBeforeUse + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation, + UIApplicationLaunchOptionsKey.openInPlace : copyBeforeUse ] } else { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation ] } - XCTAssertFalse(openURLCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertFalse(openURLCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertFalse(openURLCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertFalse(openURLCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch openURLCapableDelegate.launchItem { - case .NoItem: + case .none: break default: XCTFail() } } - + func test_applicationDidFinishLaunching_passesThroughOptions() { let openURLCapableDelegate = OpenURLCapableDelegate() - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 let copyBeforeUse = true if #available(iOS 9.0, *) { XCTAssertTrue( - openURLCapableDelegate.application(UIApplication.sharedApplication(), - didFinishLaunchingWithOptions: [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation, - UIApplicationOpenURLOptionsOpenInPlaceKey : copyBeforeUse + openURLCapableDelegate.application(UIApplication.shared, + didFinishLaunchingWithOptions: [ + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation, + UIApplicationLaunchOptionsKey.openInPlace : copyBeforeUse ] ) ) } else { XCTAssertTrue( - openURLCapableDelegate.application(UIApplication.sharedApplication(), - didFinishLaunchingWithOptions: [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation + openURLCapableDelegate.application(UIApplication.shared, + didFinishLaunchingWithOptions: [ + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation ] ) ) } switch openURLCapableDelegate.launchItem { - case let .OpenURLItem(urlToOpen): - XCTAssertEqual(urlToOpen.url, url) - XCTAssertEqual(urlToOpen.sourceApplicationBundleID, sourceBundleID) - XCTAssertEqual(urlToOpen.annotation as? Int, annotation) - XCTAssertEqual(urlToOpen.copyBeforeUse, copyBeforeUse) + case let .openURL(item): + XCTAssertEqual(item.url, url) + XCTAssertEqual(item.sourceApplicationBundleID, sourceBundleID) + XCTAssertEqual(item.annotation as? Int, annotation) + XCTAssertEqual(item.copyBeforeUse, copyBeforeUse) default: XCTFail() } @@ -106,26 +106,27 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { func test_openURL_options_passesThroughOptions() { let openURLCapableDelegate = OpenURLCapableDelegate() - openURLCapableDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) + openURLCapableDelegate.loadInterfaceOnce(with: .none) - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 let copyBeforeUse = true if #available(iOS 9.0, *) { XCTAssertTrue( - openURLCapableDelegate.application(UIApplication.sharedApplication(), - openURL: url, - options: [ - UIApplicationOpenURLOptionsSourceApplicationKey : sourceBundleID, - UIApplicationOpenURLOptionsAnnotationKey : annotation, - UIApplicationOpenURLOptionsOpenInPlaceKey : copyBeforeUse + openURLCapableDelegate.application(UIApplication.shared, + open: url, + options: [ + UIApplicationOpenURLOptionsKey.sourceApplication : sourceBundleID, + UIApplicationOpenURLOptionsKey.annotation : annotation, + UIApplicationOpenURLOptionsKey.openInPlace : copyBeforeUse ] ) ) + } else { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: url, sourceApplication: sourceBundleID, annotation: annotation)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: url, sourceApplication: sourceBundleID, annotation: annotation)) } XCTAssertEqual(openURLCapableDelegate.handledURLToOpen?.url, url) @@ -136,13 +137,13 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { func test_openURL_sourceApplication_annotation_passesThroughOptions() { let openURLCapableDelegate = OpenURLCapableDelegate() - openURLCapableDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) + openURLCapableDelegate.loadInterfaceOnce(with: .none) - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: url, sourceApplication: sourceBundleID, annotation: annotation)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: url, sourceApplication: sourceBundleID, annotation: annotation)) XCTAssertEqual(openURLCapableDelegate.handledURLToOpen?.url, url) XCTAssertEqual(openURLCapableDelegate.handledURLToOpen?.sourceApplicationBundleID, sourceBundleID) @@ -150,35 +151,35 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { XCTAssertFalse(openURLCapableDelegate.handledURLToOpen?.copyBeforeUse ?? true) } - func test_openURL_dropsURLDeliveredToLoadInterfaceWithLaunchItem() { + func test_openURL_dropsURLDeliveredToLoadInterfaceWithLaunchItem() { let openURLCapableDelegate = OpenURLCapableDelegate() - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 let copyBeforeUse = true openURLCapableDelegate.shouldOpenNextURL = true - let launchOptions: [String : AnyObject] + let launchOptions: [UIApplicationLaunchOptionsKey : Any] if #available(iOS 9.0, *) { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation, - UIApplicationOpenURLOptionsOpenInPlaceKey : copyBeforeUse + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation, + UIApplicationLaunchOptionsKey.openInPlace : copyBeforeUse ] } else { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation ] } - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch openURLCapableDelegate.launchItem { - case .OpenURLItem: + case .openURL: break default: XCTFail() @@ -188,43 +189,43 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { openURLCapableDelegate.handledURLToOpen = nil if #available(iOS 9.0, *) { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: url, options: [:])) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: url, options: [:])) } else { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: url, sourceApplication: sourceBundleID, annotation: annotation)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: url, sourceApplication: sourceBundleID, annotation: annotation)) } XCTAssertNil(openURLCapableDelegate.handledURLToOpen) - } + } func test_openURL_doesNotDropURLDeliveredToLoadInterfaceWithLaunchItemAfterApplicationWillEnterForeground() { let openURLCapableDelegate = OpenURLCapableDelegate() - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 let copyBeforeUse = true openURLCapableDelegate.shouldOpenNextURL = true - let launchOptions: [String : AnyObject] + let launchOptions: [UIApplicationLaunchOptionsKey : Any] if #available(iOS 9.0, *) { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation, - UIApplicationOpenURLOptionsOpenInPlaceKey : copyBeforeUse + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation, + UIApplicationLaunchOptionsKey.openInPlace : copyBeforeUse ] } else { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation ] } - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch openURLCapableDelegate.launchItem { - case .OpenURLItem: + case .openURL: break default: XCTFail() @@ -233,12 +234,12 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { XCTAssertNotNil(openURLCapableDelegate.handledURLToOpen) openURLCapableDelegate.handledURLToOpen = nil - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) if #available(iOS 9.0, *) { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: url, options: [:])) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: url, options: [:])) } else { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: url, sourceApplication: sourceBundleID, annotation: annotation)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: url, sourceApplication: sourceBundleID, annotation: annotation)) } XCTAssertEqual(openURLCapableDelegate.handledURLToOpen?.url, url) @@ -246,33 +247,33 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { func test_openURL_doesNotDropURLDifferentThanURLDeliveredToLoadInterfaceWithLaunchItem() { let openURLCapableDelegate = OpenURLCapableDelegate() - let url = NSURL(string: "cash.me/$dan")! + let url = URL(string: "cash.me/$dan")! let sourceBundleID = "com.squareup.cash" let annotation = 1 let copyBeforeUse = true openURLCapableDelegate.shouldOpenNextURL = true - let launchOptions: [String : AnyObject] + let launchOptions: [UIApplicationLaunchOptionsKey : Any] if #available(iOS 9.0, *) { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation, - UIApplicationOpenURLOptionsOpenInPlaceKey : copyBeforeUse + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation, + UIApplicationLaunchOptionsKey.openInPlace : copyBeforeUse ] } else { launchOptions = [ - UIApplicationLaunchOptionsURLKey : url, - UIApplicationLaunchOptionsSourceApplicationKey : sourceBundleID, - UIApplicationLaunchOptionsAnnotationKey : annotation + UIApplicationLaunchOptionsKey.url : url, + UIApplicationLaunchOptionsKey.sourceApplication : sourceBundleID, + UIApplicationLaunchOptionsKey.annotation : annotation ] } - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch openURLCapableDelegate.launchItem { - case .OpenURLItem: + case .openURL: break default: XCTFail() @@ -281,11 +282,11 @@ class SuperDelegateOpenURLTests: SuperDelegateTests { XCTAssertNotNil(openURLCapableDelegate.handledURLToOpen) openURLCapableDelegate.handledURLToOpen = nil - let otherUrl = NSURL(string: "cash.me/$martin")! + let otherUrl = URL(string: "cash.me/$martin")! if #available(iOS 9.0, *) { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: otherUrl, options: [:])) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: otherUrl, options: [:])) } else { - XCTAssertTrue(openURLCapableDelegate.application(UIApplication.sharedApplication(), openURL: otherUrl, sourceApplication: sourceBundleID, annotation: annotation)) + XCTAssertTrue(openURLCapableDelegate.application(UIApplication.shared, open: otherUrl, sourceApplication: sourceBundleID, annotation: annotation)) } XCTAssertEqual(openURLCapableDelegate.handledURLToOpen?.url, otherUrl) @@ -300,13 +301,13 @@ class OpenURLCapableDelegate: AppLaunchedDelegate, OpenURLCapable { var shouldOpenNextURL = true var handledURLToOpen: URLToOpen? - func handleURLToOpen(urlToOpen: URLToOpen) -> Bool { + func handle(urlToOpen: URLToOpen) -> Bool { handledURLToOpen = urlToOpen return shouldOpenNextURL } - func canOpenLaunchURL(launchURLToOpen: URLToOpen) -> Bool { - handledURLToOpen = launchURLToOpen + func canOpen(launchURL: URLToOpen) -> Bool { + handledURLToOpen = launchURL return shouldOpenNextURL } } diff --git a/Tests/SuperDelegate+RemoteNotificationsTests.swift b/Tests/SuperDelegate+RemoteNotificationsTests.swift index 7d64451..f45f7a0 100644 --- a/Tests/SuperDelegate+RemoteNotificationsTests.swift +++ b/Tests/SuperDelegate+RemoteNotificationsTests.swift @@ -33,21 +33,26 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { func test_registerForRemoteNotificationsWithDeviceToken_forwardsToken() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() - let deviceToken = "a token".dataUsingEncoding(NSUTF8StringEncoding)! - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) + let deviceToken = "a token".data(using: String.Encoding.utf8)! + remoteNotificationCapableDelegate.application(UIApplication.shared, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) XCTAssertEqual(deviceToken, remoteNotificationCapableDelegate.registeredDeviceToken) } func test_didFailToRegisterForRemoteNotificationsWithError_forwardsError() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() let registrationError = NSError(domain: "push registration test", code: 0, userInfo: nil) - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didFailToRegisterForRemoteNotificationsWithError: registrationError) - XCTAssertEqual(registrationError, remoteNotificationCapableDelegate.registerFailure) + remoteNotificationCapableDelegate.application(UIApplication.shared, didFailToRegisterForRemoteNotificationsWithError: registrationError) + if let registeredFailure = remoteNotificationCapableDelegate.registerFailure as? NSError { + XCTAssertEqual(registrationError, registeredFailure) + + } else { + XCTFail() + } } func test_didFinishLaunchingWithOptions_loadsInterfaceWithRemoteNotification() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -71,15 +76,15 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { let remoteNotification = RemoteNotification(remoteNotification: remoteNotificationDictionary)! XCTAssertTrue( - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), - didFinishLaunchingWithOptions: [ - UIApplicationLaunchOptionsRemoteNotificationKey : remoteNotificationDictionary + remoteNotificationCapableDelegate.application(UIApplication.shared, + didFinishLaunchingWithOptions: [ + UIApplicationLaunchOptionsKey.remoteNotification : remoteNotificationDictionary ] ) ) switch remoteNotificationCapableDelegate.launchItem { - case let .RemoteNotificationItem(launchRemoteNotification): + case let .remoteNotification(launchRemoteNotification): XCTAssertEqual(launchRemoteNotification, remoteNotification) default: XCTFail() @@ -88,7 +93,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { func test_didReceiveRemoteNotification_deliversRemoteNotificationWithProperOrigin() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -111,34 +116,34 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { ] let remoteNotification = RemoteNotification(remoteNotification: remoteNotificationDictionary)! - remoteNotificationCapableDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) + remoteNotificationCapableDelegate.loadInterfaceOnce(with: .none) var fetchCompletionHandlerExecuted = false - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didReceiveRemoteNotification: remoteNotificationDictionary) { (_) in + remoteNotificationCapableDelegate.application(UIApplication.shared, didReceiveRemoteNotification: remoteNotificationDictionary) { (_) in fetchCompletionHandlerExecuted = true } XCTAssertTrue(fetchCompletionHandlerExecuted) XCTAssertEqual(remoteNotificationCapableDelegate.receivedRemoteNotification, remoteNotification) - XCTAssertEqual(remoteNotificationCapableDelegate.receivedNotificationOrigin, UserNotificationOrigin.UserTappedToBringAppToForeground) + XCTAssertEqual(remoteNotificationCapableDelegate.receivedNotificationOrigin, UserNotificationOrigin.userTappedToBringAppToForeground) remoteNotificationCapableDelegate.applicationIsInForeground = true fetchCompletionHandlerExecuted = false - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didReceiveRemoteNotification: remoteNotificationDictionary) { (_) in + remoteNotificationCapableDelegate.application(UIApplication.shared, didReceiveRemoteNotification: remoteNotificationDictionary) { (_) in fetchCompletionHandlerExecuted = true } XCTAssertTrue(fetchCompletionHandlerExecuted) XCTAssertEqual(remoteNotificationCapableDelegate.receivedRemoteNotification, remoteNotification) - XCTAssertEqual(remoteNotificationCapableDelegate.receivedNotificationOrigin, UserNotificationOrigin.DeliveredWhileInForground) + XCTAssertEqual(remoteNotificationCapableDelegate.receivedNotificationOrigin, UserNotificationOrigin.deliveredWhileInForeground) } func test_didReceiveRemoteNotification_dropsRemoteNotificationDeliveredToLoadInterfaceWithLaunchItem() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -162,15 +167,15 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { let remoteNotification = RemoteNotification(remoteNotification: remoteNotificationDictionary)! XCTAssertTrue( - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), - didFinishLaunchingWithOptions: [ - UIApplicationLaunchOptionsRemoteNotificationKey : remoteNotificationDictionary + remoteNotificationCapableDelegate.application(UIApplication.shared, + didFinishLaunchingWithOptions: [ + UIApplicationLaunchOptionsKey.remoteNotification : remoteNotificationDictionary ] ) ) switch remoteNotificationCapableDelegate.launchItem { - case let .RemoteNotificationItem(launchRemoteNotification): + case let .remoteNotification(launchRemoteNotification): XCTAssertEqual(launchRemoteNotification, remoteNotification) default: XCTFail() @@ -178,7 +183,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { XCTAssertNil(remoteNotificationCapableDelegate.receivedRemoteNotification) - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didReceiveRemoteNotification: remoteNotificationDictionary, fetchCompletionHandler: { (_) in + remoteNotificationCapableDelegate.application(UIApplication.shared, didReceiveRemoteNotification: remoteNotificationDictionary, fetchCompletionHandler: { (_) in // Nothing to do here. }) @@ -187,7 +192,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { func test_didReceiveRemoteNotification_doesNotDropRemoteNotificationDeliveredToLoadInterfaceWithLaunchItemAfterApplicationWillEnterForeground() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -211,15 +216,15 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { let remoteNotification = RemoteNotification(remoteNotification: remoteNotificationDictionary)! XCTAssertTrue( - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), - didFinishLaunchingWithOptions: [ - UIApplicationLaunchOptionsRemoteNotificationKey : remoteNotificationDictionary + remoteNotificationCapableDelegate.application(UIApplication.shared, + didFinishLaunchingWithOptions: [ + UIApplicationLaunchOptionsKey.remoteNotification : remoteNotificationDictionary ] ) ) switch remoteNotificationCapableDelegate.launchItem { - case let .RemoteNotificationItem(launchRemoteNotification): + case let .remoteNotification(launchRemoteNotification): XCTAssertEqual(launchRemoteNotification, remoteNotification) default: XCTFail() @@ -227,9 +232,9 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { XCTAssertNil(remoteNotificationCapableDelegate.receivedRemoteNotification) - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didReceiveRemoteNotification: remoteNotificationDictionary, fetchCompletionHandler: { (_) in + remoteNotificationCapableDelegate.application(UIApplication.shared, didReceiveRemoteNotification: remoteNotificationDictionary, fetchCompletionHandler: { (_) in // Nothing to do here. }) @@ -238,7 +243,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { func test_didReceiveRemoteNotification_doesNotDropRemoteNotificationDifferentThanRemoteNotificationDeliveredToLoadInterfaceWithLaunchItem() { let remoteNotificationCapableDelegate = RemoteNotificationCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -262,15 +267,15 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { let remoteNotification = RemoteNotification(remoteNotification: remoteNotificationDictionary)! XCTAssertTrue( - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), - didFinishLaunchingWithOptions: [ - UIApplicationLaunchOptionsRemoteNotificationKey : remoteNotificationDictionary + remoteNotificationCapableDelegate.application(UIApplication.shared, + didFinishLaunchingWithOptions: [ + UIApplicationLaunchOptionsKey.remoteNotification : remoteNotificationDictionary ] ) ) switch remoteNotificationCapableDelegate.launchItem { - case let .RemoteNotificationItem(launchRemoteNotification): + case let .remoteNotification(launchRemoteNotification): XCTAssertEqual(launchRemoteNotification, remoteNotification) default: XCTFail() @@ -278,15 +283,15 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { XCTAssertNil(remoteNotificationCapableDelegate.receivedRemoteNotification) - let otherRemoteNotificationDictionary: [NSObject : AnyObject] = [ + let otherRemoteNotificationDictionary: [AnyHashable : Any] = [ alertKey : [ alertBodyKey : "other " + alertBody, alertBodyLocKey : "other" + alertBodyLocalizationKey, ] ] let otherRemoteNotification = RemoteNotification(remoteNotification: otherRemoteNotificationDictionary)! - - remoteNotificationCapableDelegate.application(UIApplication.sharedApplication(), didReceiveRemoteNotification: otherRemoteNotificationDictionary, fetchCompletionHandler: { (_) in + + remoteNotificationCapableDelegate.application(UIApplication.shared, didReceiveRemoteNotification: otherRemoteNotificationDictionary, fetchCompletionHandler: { (_) in // Nothing to do here. }) @@ -299,7 +304,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { func test_receivingRemoteNotificationAction_notifies() { let remoteNotificationActionCapableDelegate = RemoteNotificationActionCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -324,7 +329,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { let actionIdentifier = "some action" var completionHandlerExecuted = false - remoteNotificationActionCapableDelegate.application(UIApplication.sharedApplication(), handleActionWithIdentifier: actionIdentifier, forRemoteNotification: remoteNotificationDictionary) { + remoteNotificationActionCapableDelegate.application(UIApplication.shared, handleActionWithIdentifier: actionIdentifier, forRemoteNotification: remoteNotificationDictionary) { completionHandlerExecuted = true } @@ -336,7 +341,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { func test_receivingLocalNotificationWithResponseInfoAction_notifies() { let remoteNotificationActionCapableDelegate = RemoteNotificationActionCapableDelegate() - let remoteNotificationDictionary: [NSObject : AnyObject] = [ + let remoteNotificationDictionary: [AnyHashable : Any] = [ APSServiceKey : [ alertKey : [ alertBodyKey : alertBody, @@ -362,7 +367,7 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { let responseInfo = ["a response" : "object"] var completionHandlerExecuted = false - remoteNotificationActionCapableDelegate.application(UIApplication.sharedApplication(), handleActionWithIdentifier: actionIdentifier, forRemoteNotification: remoteNotificationDictionary, withResponseInfo: responseInfo) { + remoteNotificationActionCapableDelegate.application(UIApplication.shared, handleActionWithIdentifier: actionIdentifier, forRemoteNotification: remoteNotificationDictionary, withResponseInfo: responseInfo) { completionHandlerExecuted = true } @@ -379,22 +384,22 @@ class SuperDelegateRemoteNotificationTests: SuperDelegateTests { class RemoteNotificationCapableDelegate: AppLaunchedDelegate, RemoteNotificationCapable { - var registeredDeviceToken: NSData? - func didRegisterForRemoteNotificationsWithToken(deviceToken: NSData) { + var registeredDeviceToken: Data? + func didRegisterForRemoteNotifications(withDeviceToken deviceToken: Data) { registeredDeviceToken = deviceToken } - var registerFailure: NSError? - func didFailToRegisterForRemoteNotificationsWithError(error: NSError) { + var registerFailure: Error? + func didFailToRegisterForRemoteNotifications(withError error: Error) { registerFailure = error } var receivedRemoteNotification: RemoteNotification? var receivedNotificationOrigin: UserNotificationOrigin? - func didReceiveRemoteNotification(remoteNotification: RemoteNotification, notificationOrigin: UserNotificationOrigin, fetchCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)) { + func didReceive(remoteNotification: RemoteNotification, origin: UserNotificationOrigin, fetchCompletionHandler completionHandler: @escaping ((UIBackgroundFetchResult) -> Swift.Void)) { receivedRemoteNotification = remoteNotification - receivedNotificationOrigin = notificationOrigin - completionHandler(.NoData) + receivedNotificationOrigin = origin + completionHandler(.noData) } } @@ -408,14 +413,14 @@ class RemoteNotificationActionCapableDelegate: RemoteNotificationCapableDelegate return UIUserNotificationSettings() } - func didReceiveUserNotificationPermissions(userNotificationPermissionsGranted: UserNotificationPermissionsGranted) { + func didReceive(userNotificationPermissions: UserNotificationPermissionsGranted) { } var handledActionIdentifier: String? = "" - var handledRemoteNotification = RemoteNotification(remoteNotification: [NSObject : AnyObject]()) - var handledResponseInfo: [String : AnyObject]? = nil - func handleRemoteNotificationActionWithIdentifier(actionIdentifier: String?, forRemoteNotification notification: RemoteNotification, withResponseInfo responseInfo: [String : AnyObject]?, completionHandler: () -> Void) { + var handledRemoteNotification = RemoteNotification(remoteNotification: [AnyHashable : Any]()) + var handledResponseInfo: [String : Any]? = nil + func handleRemoteNotificationAction(withActionIdentifier actionIdentifier: String?, forRemoteNotification notification: RemoteNotification, withResponseInfo responseInfo: [String : Any]?, completionHandler: @escaping () -> Swift.Void) { handledActionIdentifier = actionIdentifier handledRemoteNotification = notification handledResponseInfo = responseInfo diff --git a/Tests/SuperDelegate+ShortcutsTests.swift b/Tests/SuperDelegate+ShortcutsTests.swift index 47a50c4..78a9da0 100644 --- a/Tests/SuperDelegate+ShortcutsTests.swift +++ b/Tests/SuperDelegate+ShortcutsTests.swift @@ -35,26 +35,26 @@ class SuperDelegateShortcutsTests: SuperDelegateTests { shortcutCapableDelegate.shouldHandleNextShortcut = false let launchOptions = [ - UIApplicationLaunchOptionsShortcutItemKey : shortcutItem, - ] + UIApplicationLaunchOptionsKey.shortcutItem : shortcutItem, + ] - XCTAssertTrue(shortcutCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(shortcutCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(shortcutCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(shortcutCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch shortcutCapableDelegate.launchItem { - case .NoItem: + case .none: break default: XCTFail() } } - func test_performActionForShortcutItem_doesNotCallHandleShortcutItemToOpenIfCanHandleShortcutItemFails() { + func test_performActionFor_doesNotCallHandleShortcutItemToOpenIfCanHandleShortcutItemFails() { let shortcutCapableDelegate = ShortcutsCapableDelegate() let shortcutItem = UIApplicationShortcutItem(type: "a shortcut type", localizedTitle: "the best shortcut title") shortcutCapableDelegate.shouldHandleNextShortcut = false - shortcutCapableDelegate.application(UIApplication.sharedApplication(), performActionForShortcutItem: shortcutItem) { (handledShortcutItem) in + shortcutCapableDelegate.application(UIApplication.shared, performActionFor: shortcutItem) { (handledShortcutItem) in XCTAssertFalse(handledShortcutItem) } @@ -66,26 +66,26 @@ class SuperDelegateShortcutsTests: SuperDelegateTests { let shortcutItem = UIApplicationShortcutItem(type: "a shortcut type", localizedTitle: "the best shortcut title") let launchOptions = [ - UIApplicationLaunchOptionsShortcutItemKey : shortcutItem, + UIApplicationLaunchOptionsKey.shortcutItem : shortcutItem, ] - XCTAssertFalse(shortcutCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(shortcutCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertFalse(shortcutCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(shortcutCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch shortcutCapableDelegate.launchItem { - case let .ShortcutItem(launchShortcutItem): + case let .shortcut(launchShortcutItem): XCTAssertEqual(shortcutItem, launchShortcutItem) default: XCTFail() } } - func test_performActionForShortcutItem_callsHandleShortcutItemToOpenIfCanHandleShortcutItemSucceeds() { + func test_performActionFor_callsHandleShortcutItemToOpenIfCanHandleShortcutItemSucceeds() { let shortcutCapableDelegate = ShortcutsCapableDelegate() let shortcutItem = UIApplicationShortcutItem(type: "a shortcut type", localizedTitle: "the best shortcut title") - shortcutCapableDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) - shortcutCapableDelegate.application(UIApplication.sharedApplication(), performActionForShortcutItem: shortcutItem) { (handledShortcutItem) in + shortcutCapableDelegate.loadInterfaceOnce(with: .none) + shortcutCapableDelegate.application(UIApplication.shared, performActionFor: shortcutItem) { (handledShortcutItem) in XCTAssertTrue(handledShortcutItem) } @@ -101,12 +101,12 @@ class SuperDelegateShortcutsTests: SuperDelegateTests { class ShortcutsCapableDelegate: AppLaunchedDelegate, ShortcutCapable { var shouldHandleNextShortcut = true - func canHandleShortcutItem(shortcutItem: UIApplicationShortcutItem) -> Bool { + func canHandle(shortcutItem: UIApplicationShortcutItem) -> Bool { return shouldHandleNextShortcut } var handledShortcut: UIApplicationShortcutItem? - func handleShortcutItem(shortcutItem: UIApplicationShortcutItem, completionHandler: () -> Void) { + func handle(shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping () -> Swift.Void) { handledShortcut = shortcutItem completionHandler() } diff --git a/Tests/SuperDelegate+StateRestorationTests.swift b/Tests/SuperDelegate+StateRestorationTests.swift index e7a9dac..a85b13f 100644 --- a/Tests/SuperDelegate+StateRestorationTests.swift +++ b/Tests/SuperDelegate+StateRestorationTests.swift @@ -30,17 +30,17 @@ class SuperDelegateStateRestorationTests: SuperDelegateTests { func test_applicationWillFinishLaunching_loadsInterface() { let stateRestorationCapableDelegate = StateRestorationCapableDelegate() - XCTAssertTrue(stateRestorationCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: nil)) + XCTAssertTrue(stateRestorationCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: nil)) XCTAssertTrue(stateRestorationCapableDelegate.interfaceLoaded) switch stateRestorationCapableDelegate.launchItem { - case .NoItem: + case .none: break default: XCTFail() } - XCTAssertTrue(stateRestorationCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: nil)) + XCTAssertTrue(stateRestorationCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)) } } @@ -50,25 +50,25 @@ class SuperDelegateStateRestorationTests: SuperDelegateTests { class StateRestorationCapableDelegate: AppLaunchedDelegate, StateRestorationCapable { - func shouldSaveApplicationState(coder: NSCoder) -> Bool { + func shouldSaveApplicationState(using coder: NSCoder) -> Bool { // Nothing to test here. This method is just a passthrough. return true } - func shouldRestoreApplicationState(coder: NSCoder) -> Bool { + func shouldRestoreApplicationState(using coder: NSCoder) -> Bool { // Nothing to test here. This method is just a passthrough. return true } - func willEncodeRestorableStateWithCoder(coder: NSCoder) { + func willEncodeRestorableState(using coder: NSCoder) { // Nothing to test here. This method is just a passthrough. } - func didDecodeRestorableStateWithCoder(coder: NSCoder) { + func didDecodeRestorableState(using coder: NSCoder) { // Nothing to test here. This method is just a passthrough. } - func viewControllerWithRestorationIdentifierPath(identifierComponents: [AnyObject], coder: NSCoder) -> UIViewController? { + func viewControllerWithRestorationIdentifierPath(identifierComponents: [Any], coder: NSCoder) -> UIViewController? { // Nothing to test here. This method is just a passthrough. return nil; } diff --git a/Tests/SuperDelegate+UserActivityTests.swift b/Tests/SuperDelegate+UserActivityTests.swift index 27dc41e..209de62 100644 --- a/Tests/SuperDelegate+UserActivityTests.swift +++ b/Tests/SuperDelegate+UserActivityTests.swift @@ -34,17 +34,17 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { userActivityCapableDelegate.shouldHandleNextUserActivity = false let launchOptions = [ - UIApplicationLaunchOptionsUserActivityDictionaryKey : [ - ApplicationLaunchOptionsUserActivityKey : NSUserActivity(activityType: userActivityType), - UIApplicationLaunchOptionsUserActivityTypeKey : userActivityType + UIApplicationLaunchOptionsKey.userActivityDictionary : [ + UIApplicationLaunchOptionsKey.userActivity : NSUserActivity(activityType: userActivityType), + UIApplicationLaunchOptionsKey.userActivityType : userActivityType ] ] - XCTAssertFalse(userActivityCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertFalse(userActivityCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertFalse(userActivityCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertFalse(userActivityCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch userActivityCapableDelegate.launchItem { - case .NoItem: + case .none: break default: XCTFail() @@ -56,9 +56,10 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { let userActivityType = "does this look like user activity to you?" userActivityCapableDelegate.shouldHandleNextUserActivity = false - XCTAssertFalse(userActivityCapableDelegate.application(UIApplication.sharedApplication(), continueUserActivity: NSUserActivity(activityType: userActivityType)) { (_) in + XCTAssertFalse(userActivityCapableDelegate.application(UIApplication.shared, continue: NSUserActivity(activityType: userActivityType)) { (_) in // Nothing to do here. - }) + } + ) XCTAssertNil(userActivityCapableDelegate.continuedUserActivity) } @@ -67,10 +68,10 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { let userActivityCapableDelegate = UserActivityCapableDelegate() let userActivity = NSUserActivity(activityType: "does this look like user activity to you?") - userActivityCapableDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), continueUserActivity: userActivity) { (_) in + userActivityCapableDelegate.loadInterfaceOnce(with: .none) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, continue: userActivity) { (_) in // Nothing to do here. - }) + }) XCTAssertEqual(userActivity, userActivityCapableDelegate.continuedUserActivity) } @@ -80,17 +81,17 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { let userActivityType = "does this look like user activity to you?" let launchOptions = [ - UIApplicationLaunchOptionsUserActivityDictionaryKey : [ - ApplicationLaunchOptionsUserActivityKey : NSUserActivity(activityType: userActivityType), - UIApplicationLaunchOptionsUserActivityTypeKey : userActivityType + UIApplicationLaunchOptionsKey.userActivityDictionary : [ + UIApplicationLaunchOptionsKey.userActivity : NSUserActivity(activityType: userActivityType), + UIApplicationLaunchOptionsKey.userActivityType : userActivityType ] ] - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch userActivityCapableDelegate.launchItem { - case let .UserActivityItem(launchUserActivity): + case let .userActivity(launchUserActivity): XCTAssertEqual(userActivityType, launchUserActivity.activityType) default: XCTFail() @@ -103,17 +104,17 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { let userActivity = NSUserActivity(activityType: userActivityType) let launchOptions = [ - UIApplicationLaunchOptionsUserActivityDictionaryKey : [ - ApplicationLaunchOptionsUserActivityKey : userActivity, - UIApplicationLaunchOptionsUserActivityTypeKey : userActivityType + UIApplicationLaunchOptionsKey.userActivityDictionary : [ + UIApplicationLaunchOptionsKey.userActivity : userActivity, + UIApplicationLaunchOptionsKey.userActivityType : userActivityType ] ] - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch userActivityCapableDelegate.launchItem { - case let .UserActivityItem(launchUserActivity): + case let .userActivity(launchUserActivity): XCTAssertEqual(userActivityType, launchUserActivity.activityType) default: XCTFail() @@ -121,7 +122,7 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { XCTAssertNil(userActivityCapableDelegate.continuedUserActivity) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), continueUserActivity: userActivity, restorationHandler: { (_) in + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, continue: userActivity, restorationHandler: { (_) in // Nothing to do here })) @@ -133,19 +134,18 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { let userActivityType = "does this look like user activity to you?" let userActivity = NSUserActivity(activityType: userActivityType) - let launchOptions = [ - UIApplicationLaunchOptionsUserActivityDictionaryKey : [ - ApplicationLaunchOptionsUserActivityKey : userActivity, - UIApplicationLaunchOptionsUserActivityTypeKey : userActivityType + UIApplicationLaunchOptionsKey.userActivityDictionary : [ + UIApplicationLaunchOptionsKey.userActivity : userActivity, + UIApplicationLaunchOptionsKey.userActivityType : userActivityType ] ] - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch userActivityCapableDelegate.launchItem { - case let .UserActivityItem(launchUserActivity): + case let .userActivity(launchUserActivity): XCTAssertEqual(userActivityType, launchUserActivity.activityType) default: XCTFail() @@ -153,9 +153,9 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { XCTAssertNil(userActivityCapableDelegate.continuedUserActivity) - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), continueUserActivity: userActivity, restorationHandler: { (_) in + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, continue: userActivity, restorationHandler: { (_) in // Nothing to do here })) @@ -167,19 +167,18 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { let userActivityType = "does this look like user activity to you?" let userActivity = NSUserActivity(activityType: userActivityType) - let launchOptions = [ - UIApplicationLaunchOptionsUserActivityDictionaryKey : [ - ApplicationLaunchOptionsUserActivityKey : userActivity, - UIApplicationLaunchOptionsUserActivityTypeKey : userActivityType + UIApplicationLaunchOptionsKey.userActivityDictionary : [ + UIApplicationLaunchOptionsKey.userActivity : userActivity, + UIApplicationLaunchOptionsKey.userActivityType : userActivityType ] ] - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: launchOptions)) - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: launchOptions)) + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: launchOptions)) switch userActivityCapableDelegate.launchItem { - case let .UserActivityItem(launchUserActivity): + case let .userActivity(launchUserActivity): XCTAssertEqual(userActivityType, launchUserActivity.activityType) default: XCTFail() @@ -188,7 +187,7 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { XCTAssertNil(userActivityCapableDelegate.continuedUserActivity) let anotherUserActivity = NSUserActivity(activityType: "Some other user activity") - XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.sharedApplication(), continueUserActivity: anotherUserActivity, restorationHandler: { (_) in + XCTAssertTrue(userActivityCapableDelegate.application(UIApplication.shared, continue: anotherUserActivity, restorationHandler: { (_) in // Nothing to do here })) @@ -202,12 +201,12 @@ class SuperDelegateUserActivityTests: SuperDelegateTests { class UserActivityCapableDelegate: AppLaunchedDelegate, UserActivityCapable { var shouldHandleNextUserActivity = true - func canHandleUserActivity(userActivity: NSUserActivity) -> Bool { + func canResume(userActivity: NSUserActivity) -> Bool { return shouldHandleNextUserActivity } var continuedUserActivity: NSUserActivity? - func continueUserActivity(userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool { + func resume(userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Swift.Void) -> Bool { continuedUserActivity = userActivity return true } diff --git a/Tests/SuperDelegate+UserNotificationsTests.swift b/Tests/SuperDelegate+UserNotificationsTests.swift index 9395c37..2dea5d3 100644 --- a/Tests/SuperDelegate+UserNotificationsTests.swift +++ b/Tests/SuperDelegate+UserNotificationsTests.swift @@ -30,11 +30,11 @@ class SuperDelegateUserNotificationTests: SuperDelegateTests { func test_requestUserNotificationPermissions_isNotCalledOnWillEnterForegroundIfNotPreviouslyCalled() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: nil)) - XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)) XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 1) - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) // One call for testing if we've previously registered. XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 2) @@ -43,8 +43,8 @@ class SuperDelegateUserNotificationTests: SuperDelegateTests { func test_requestUserNotificationPermissions_isCalledOnWillEnterForegroundIfPreviouslyCalled() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: nil)) - XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)) // One call on willFinishLaunching is expected. XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 1) @@ -52,7 +52,7 @@ class SuperDelegateUserNotificationTests: SuperDelegateTests { // One call for registering, one call for noting that we registered. XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 3) - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) // One call for testing if we've previously registered, one call for registering, one call for setting that we have registered. XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 6) @@ -61,26 +61,26 @@ class SuperDelegateUserNotificationTests: SuperDelegateTests { func test_requestUserNotificationPermissions_isNotCalledOnWillEnterForegroundIfPreviouslyCalledWithDifferentNotificationTypes() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: nil)) - XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)) XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 1) userNotificationsCapableDelegate.requestUserNotificationPermissions() // One call for registering, one call for noting that we registered. XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 3) - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) // One call for testing if we've previously registered, one call for registering, one call for setting that we have registered. XCTAssertEqual(userNotificationsCapableDelegate.requestedUserNotificationSettingsCallCount, 6) // A new instance should be able to read from the same pref and register (or not) accordingly. let userNotificationsCapableDelegateWithDifferentUserNotificationPreferences = UserNotificationsCapableDelegate() - userNotificationsCapableDelegateWithDifferentUserNotificationPreferences.userNotificationSettingsToPrefer = UIUserNotificationSettings(forTypes: UIUserNotificationType.Alert, categories: nil) + userNotificationsCapableDelegateWithDifferentUserNotificationPreferences.userNotificationSettingsToPrefer = UIUserNotificationSettings(types: UIUserNotificationType.alert, categories: nil) - XCTAssertTrue(userNotificationsCapableDelegateWithDifferentUserNotificationPreferences.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: nil)) + XCTAssertTrue(userNotificationsCapableDelegateWithDifferentUserNotificationPreferences.application(UIApplication.shared, willFinishLaunchingWithOptions: nil)) XCTAssertEqual(userNotificationsCapableDelegateWithDifferentUserNotificationPreferences.requestedUserNotificationSettingsCallCount, 1) - NSNotificationCenter.defaultCenter().postNotificationName(UIApplicationWillEnterForegroundNotification, object: UIApplication.sharedApplication()) + NotificationCenter.default.post(name: NSNotification.Name.UIApplicationWillEnterForeground, object: UIApplication.shared) // One call for testing if we've previously registered, but none for registering. XCTAssertEqual(userNotificationsCapableDelegateWithDifferentUserNotificationPreferences.requestedUserNotificationSettingsCallCount, 1) @@ -90,35 +90,36 @@ class SuperDelegateUserNotificationTests: SuperDelegateTests { func test_didReceiveUserNotificationPermissions_saysRequestedPermissionsGrantedWhenNoneAreRequsted() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didRegisterUserNotificationSettings: UIUserNotificationSettings()) + userNotificationsCapableDelegate.application(UIApplication.shared, didRegister: UIUserNotificationSettings()) - XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.Requested) + + XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.requested) } func test_didReceiveUserNotificationPermissions_saysNonePermissionsGrantedWhenAllAreRequstedAndNoneGranted() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - userNotificationsCapableDelegate.userNotificationSettingsToPrefer = UIUserNotificationSettings(forTypes: UIUserNotificationType(rawValue: (UIUserNotificationType.Alert.rawValue | UIUserNotificationType.Sound.rawValue | UIUserNotificationType.Badge.rawValue)), categories: nil) - userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didRegisterUserNotificationSettings: UIUserNotificationSettings()) + userNotificationsCapableDelegate.userNotificationSettingsToPrefer = UIUserNotificationSettings(types: UIUserNotificationType(rawValue: (UIUserNotificationType.alert.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.badge.rawValue)), categories: nil) + userNotificationsCapableDelegate.application(UIApplication.shared, didRegister: UIUserNotificationSettings()) - XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.None) + XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.none) } func test_didReceiveUserNotificationPermissions_saysRequestedPermissionsGrantedWhenAllAreRequstedAndGranted() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - let preferredUserNotificationTypes = UIUserNotificationType(rawValue: (UIUserNotificationType.Alert.rawValue | UIUserNotificationType.Sound.rawValue | UIUserNotificationType.Badge.rawValue)) - userNotificationsCapableDelegate.userNotificationSettingsToPrefer = UIUserNotificationSettings(forTypes: preferredUserNotificationTypes, categories: nil) - userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didRegisterUserNotificationSettings: UIUserNotificationSettings(forTypes: preferredUserNotificationTypes, categories: nil)) + let preferredUserNotificationTypes = UIUserNotificationType(rawValue: (UIUserNotificationType.alert.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.badge.rawValue)) + userNotificationsCapableDelegate.userNotificationSettingsToPrefer = UIUserNotificationSettings(types: preferredUserNotificationTypes, categories: nil) + userNotificationsCapableDelegate.application(UIApplication.shared, didRegister: UIUserNotificationSettings(types: preferredUserNotificationTypes, categories: nil)) - XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.Requested) + XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.requested) } func test_didReceiveUserNotificationPermissions_saysSomePermissionsGrantedWhenAllAreRequstedAndGranted() { let userNotificationsCapableDelegate = UserNotificationsCapableDelegate() - let preferredUserNotificationTypes = UIUserNotificationType(rawValue: (UIUserNotificationType.Alert.rawValue | UIUserNotificationType.Sound.rawValue | UIUserNotificationType.Badge.rawValue)) - userNotificationsCapableDelegate.userNotificationSettingsToPrefer = UIUserNotificationSettings(forTypes: preferredUserNotificationTypes, categories: nil) - userNotificationsCapableDelegate.application(UIApplication.sharedApplication(), didRegisterUserNotificationSettings: UIUserNotificationSettings(forTypes: UIUserNotificationType.Badge, categories: nil)) + let preferredUserNotificationTypes = UIUserNotificationType(rawValue: (UIUserNotificationType.alert.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.badge.rawValue)) + userNotificationsCapableDelegate.userNotificationSettingsToPrefer = UIUserNotificationSettings(types: preferredUserNotificationTypes, categories: nil) + userNotificationsCapableDelegate.application(UIApplication.shared, didRegister: UIUserNotificationSettings(types: UIUserNotificationType.badge, categories: nil)) - XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.Some(grantedPermissions: UIUserNotificationType.Badge)) + XCTAssertEqual(userNotificationsCapableDelegate.grantedUserNotificationPermissions, UserNotificationPermissionsGranted.partial(grantedPermissions: UIUserNotificationType.badge)) } } @@ -135,8 +136,8 @@ class UserNotificationsCapableDelegate: AppLaunchedDelegate, UserNotificationCap return userNotificationSettingsToPrefer } - var grantedUserNotificationPermissions = UserNotificationPermissionsGranted.None - func didReceiveUserNotificationPermissions(userNotificationPermissionsGranted: UserNotificationPermissionsGranted) { - grantedUserNotificationPermissions = userNotificationPermissionsGranted + var grantedUserNotificationPermissions = UserNotificationPermissionsGranted.none + func didReceive(userNotificationPermissions: UserNotificationPermissionsGranted) { + grantedUserNotificationPermissions = userNotificationPermissions } } diff --git a/Tests/SuperDelegate+WatchKitTests.swift b/Tests/SuperDelegate+WatchKitTests.swift index ec43d28..5937809 100644 --- a/Tests/SuperDelegate+WatchKitTests.swift +++ b/Tests/SuperDelegate+WatchKitTests.swift @@ -30,7 +30,7 @@ class SuperDelegateWatchKitTests: SuperDelegateTests { func test_handleWatchkitExtensionRequest_setsUpApplicationPriorToHandlingTheExtension() { let watchKitCapableDelegate = WatchKitCapableDelegate() - watchKitCapableDelegate.application(UIApplication.sharedApplication(), handleWatchKitExtensionRequest: nil) { (_) in + watchKitCapableDelegate.application(UIApplication.shared, handleWatchKitExtensionRequest: nil) { (_) in // Nothing to do here. } XCTAssertTrue(watchKitCapableDelegate.hasHandledWatchKitExtensionRequest) @@ -44,7 +44,7 @@ class SuperDelegateWatchKitTests: SuperDelegateTests { class WatchKitCapableDelegate: AppLaunchedDelegate, WatchKitCapable { var hasHandledWatchKitExtensionRequest = false - func handleWatchKitExtensionRequest(userInfo: [NSObject : AnyObject]?, reply: ([NSObject : AnyObject]?) -> Void) { + func handleWatchKitExtensionRequest(userInfo: [AnyHashable : Any]?, reply: @escaping ([AnyHashable : Any]?) -> Swift.Void) { hasHandledWatchKitExtensionRequest = true XCTAssertTrue(hasSetupApplication) } diff --git a/Tests/SuperDelegateTests.swift b/Tests/SuperDelegateTests.swift index 4266189..d82c190 100644 --- a/Tests/SuperDelegateTests.swift +++ b/Tests/SuperDelegateTests.swift @@ -33,14 +33,14 @@ class SuperDelegateTests: XCTestCase { func test_willFinishLaunchingWithOptions_notesImproperAPIUsage() { let nonConformingTestDelegate = NonConformingTestDelegate() nonConformingTestDelegate.expectImproperAPIUsage = true - XCTAssertFalse(nonConformingTestDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: nil)) + XCTAssertFalse(nonConformingTestDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: nil)) XCTAssertFalse(nonConformingTestDelegate.expectImproperAPIUsage) } func test_didFinishLaunchingWithOptions_notesImproperAPIUsage() { let nonConformingTestDelegate = NonConformingTestDelegate() nonConformingTestDelegate.expectImproperAPIUsage = true - XCTAssertFalse(nonConformingTestDelegate.application(UIApplication.sharedApplication(), didFinishLaunchingWithOptions: nil)) + XCTAssertFalse(nonConformingTestDelegate.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)) XCTAssertFalse(nonConformingTestDelegate.expectImproperAPIUsage) } @@ -55,7 +55,7 @@ class SuperDelegateTests: XCTestCase { func test_loadInterfaceOnce_notesImproperAPIUsageAndGuardsAgainstLoadingInterface() { let nonConformingTestDelegate = NonConformingTestDelegate() nonConformingTestDelegate.expectImproperAPIUsage = true - nonConformingTestDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) + nonConformingTestDelegate.loadInterfaceOnce(with: .none) XCTAssertFalse(nonConformingTestDelegate.expectImproperAPIUsage) XCTAssertFalse(nonConformingTestDelegate.interfaceLoaded) } @@ -75,18 +75,18 @@ class SuperDelegateTests: XCTestCase { func test_loadInterfaceOnce_loadsInterfaceOnce() { let appLaunchedDelegate = AppLaunchedDelegate() XCTAssertFalse(appLaunchedDelegate.interfaceLoaded) - appLaunchedDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) + appLaunchedDelegate.loadInterfaceOnce(with: .none) XCTAssertTrue(appLaunchedDelegate.interfaceLoaded) - appLaunchedDelegate.loadInterfaceOnceWithLaunchItem(.NoItem) + appLaunchedDelegate.loadInterfaceOnce(with: .none) } func test_applicationWillFinishLaunching_notesImproperAPIUsageAndReturnsFalseWhenUnsupportedLaunchOptionUserActivityPresent() { let appLaunchedDelegate = AppLaunchedDelegate() appLaunchedDelegate.expectImproperAPIUsage = true // Must return false to signal that the URL user activity could not be handled. - XCTAssertFalse(appLaunchedDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsUserActivityDictionaryKey : [ApplicationLaunchOptionsUserActivityKey : NSUserActivity(activityType: "a type")]])) + XCTAssertFalse(appLaunchedDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsKey.userActivityDictionary : [UIApplicationLaunchOptionsKey.userActivity : NSUserActivity(activityType: "a type")]])) XCTAssertFalse(appLaunchedDelegate.expectImproperAPIUsage) - XCTAssertEqual(appLaunchedDelegate.launchItem, LaunchItem.NoItem) + XCTAssertEqual(appLaunchedDelegate.launchItem, LaunchItem.none) } @available(iOS 9.0, *) @@ -94,25 +94,25 @@ class SuperDelegateTests: XCTestCase { let appLaunchedDelegate = AppLaunchedDelegate() appLaunchedDelegate.expectImproperAPIUsage = true // Must return true to signal that the shortcut wasn't handled. - XCTAssertTrue(appLaunchedDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsShortcutItemKey : UIApplicationShortcutItem(type: "A type", localizedTitle: "A title")])) + XCTAssertTrue(appLaunchedDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsKey.shortcutItem : UIApplicationShortcutItem(type: "A type", localizedTitle: "A title")])) XCTAssertFalse(appLaunchedDelegate.expectImproperAPIUsage) - XCTAssertEqual(appLaunchedDelegate.launchItem, LaunchItem.NoItem) + XCTAssertEqual(appLaunchedDelegate.launchItem, LaunchItem.none) } - + func test_applicationWillFinishLaunching_notesImproperAPIUsageAndReturnsFalseWhenUnsupportedLaunchOptionURLPresent() { let appLaunchedDelegate = AppLaunchedDelegate() appLaunchedDelegate.expectImproperAPIUsage = true // Must return false to signal that the URL can not be handled. - XCTAssertFalse(appLaunchedDelegate.application(UIApplication.sharedApplication(), willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsURLKey : NSURL(fileURLWithPath: "/")])) + XCTAssertFalse(appLaunchedDelegate.application(UIApplication.shared, willFinishLaunchingWithOptions: [UIApplicationLaunchOptionsKey.url : URL(fileURLWithPath: "/")])) XCTAssertFalse(appLaunchedDelegate.expectImproperAPIUsage) - XCTAssertEqual(appLaunchedDelegate.launchItem, LaunchItem.NoItem) + XCTAssertEqual(appLaunchedDelegate.launchItem, LaunchItem.none) } func test_setupMainWindow_notesImproperAPIUsageWhenCalledOutsideOfLoadInterfaceWithLaunchItem() { let appLaunchedDelegate = AppLaunchedDelegate() appLaunchedDelegate.expectImproperAPIUsage = true - appLaunchedDelegate.setupMainWindow(UIWindow()) + appLaunchedDelegate.setup(mainWindow: UIWindow()) XCTAssertFalse(appLaunchedDelegate.expectImproperAPIUsage) } } @@ -130,7 +130,7 @@ class NonConformingTestDelegate: SuperDelegate { var expectImproperAPIUsage = false - override func noteImproperAPIUsage(text: String) { + override func noteImproperAPIUsage(_ text: String) { XCTAssertTrue(expectImproperAPIUsage) expectImproperAPIUsage = false @@ -150,8 +150,8 @@ class AppLaunchedDelegate: NonConformingTestDelegate, ApplicationLaunched { } var hasLoadedApplication = false - var launchItem = LaunchItem.NoItem - func loadInterfaceWithLaunchItem(launchItem: LaunchItem) { + var launchItem = LaunchItem.none + func loadInterface(launchItem: LaunchItem) { XCTAssertFalse(hasLoadedApplication) hasLoadedApplication = true